package com.huilian.iotbox.admin.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.iot.model.v20180120.RegisterDeviceResponse;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.huilian.iotbox.admin.dao.DeviceDao;
import com.huilian.iotbox.admin.producer.RabbitProducer;
import com.huilian.iotbox.admin.service.*;
import com.huilian.iotbox.aliyun.openapi.DeviceManager;
import com.huilian.iotbox.aliyun.service.PubService;
import com.huilian.iotbox.data.cmd.HuiLianDuiBiJiPositiveDataFrameCMD;
import com.huilian.iotbox.data.cmd.PositiveDataFrameCMD;
import com.huilian.iotbox.data.cmd.RespondDataFrameCMD;
import com.huilian.iotbox.data.cmd.VendmachPositiveDataFrameCMD;
import com.huilian.iotbox.data.common.RedisKey;
import com.huilian.iotbox.data.common.ServerResponse;
import com.huilian.iotbox.data.dto.*;
import com.huilian.iotbox.data.enums.*;
import com.huilian.iotbox.data.po.*;
import com.huilian.iotbox.data.properties.ConfigProperties;
import com.huilian.iotbox.data.properties.FileProperties;
import com.huilian.iotbox.data.service.AppletOrOfficialAccountCommonService;
import com.huilian.iotbox.data.service.ErrorLogCommonService;
import com.huilian.iotbox.data.service.ProductFuncCommonService;
import com.huilian.iotbox.data.service.SystemConfigService;
import com.huilian.iotbox.data.utils.*;
import com.huilian.iotbox.data.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.text.StrBuilder;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.math.BigDecimal;
import java.security.NoSuchAlgorithmException;
import java.time.LocalDate;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author 谢洛涛
 * @date 2021/3/31 12:05
 */
@Slf4j
@Service
public class DeviceServiceImpl implements DeviceService {

    @Value("${huilian.iot.productKey}")
    private String productKey;
    @Resource
    private DeviceDao deviceDao;
    @Value("${huilian.iot.iotInstanceId:#{null}}")
    private String iotInstanceId;
    @Autowired
    private PubService pubService;
    @Autowired
    private BaudService baudService;
    @Autowired
    private OrderService orderService;
    @Autowired
    private AgencyService agencyService;
    @Autowired
    private FileProperties fileProperties;
    @Autowired
    private RabbitProducer rabbitProducer;
    @Autowired
    private ConfigProperties configProperties;
    @Autowired
    private DeviceItemService deviceItemService;
    @Autowired
    private DisplayRackService displayRackService;
    @Autowired
    private SystemConfigService systemConfigService;
    @Autowired
    private MerchantStoreService merchantStoreService;
    @Autowired
    private MerchantBannerService merchantBannerService;
    @Autowired
    private ErrorLogCommonService errorLogCommonService;
    @Autowired
    private DisplayRackItemService displayRackItemService;
    @Autowired
    private DeviceAnnualFeeService deviceAnnualFeeService;
    @Autowired
    private CustomerServiceInfoService customerServiceInfoService;
    @Autowired
    private RedisTemplate<String, Serializable> redisCacheTemplate;
    @Autowired
    private CommodityStoreUpDownService commodityStoreUpDownService;
    @Autowired
    private AppletOrOfficialAccountCommonService appletOrOfficialAccountCommonService;

    @Override
    public List<DeviceVo> findDevice(DeviceDto deviceDto) {
        return deviceDao.findDevice(deviceDto);

    }

    @Override
    public PageInfo findDeviceList(DeviceDto deviceDto) {
        PageHelper.startPage(deviceDto.getPageNum(), deviceDto.getPageSize());
        List<DeviceVo> deviceVoList = deviceDao.findDeviceList(deviceDto);

        for (DeviceVo deviceVo : deviceVoList) {
            DeviceItem deviceItemCondition = new DeviceItem();
            deviceItemCondition.setDeviceId(deviceVo.getId());
            List<DeviceItem> deviceItemList = deviceItemService.findAllByDeviceId(deviceItemCondition);
            if (StringUtils.isEmpty(deviceItemList)) {
                deviceItemList = new ArrayList<>();
            }
            List<DeviceItemVo> deviceItemVoList = new ArrayList<>();

            for (DeviceItem deviceItem : deviceItemList) {
                DeviceItemVo deviceItemVo = new DeviceItemVo();
                BeanUtils.copyProperties(deviceItem, deviceItemVo);
                if (!StringUtils.isEmpty(deviceItemVo.getPositionId())) {
                    deviceItemVo.setHierarchy(DeviceItemPositionEnum.getHierarchy(deviceItemVo.getPositionId()));
                }
                if (StringUtils.isEmpty(deviceItemVo.getProductId())) {
                    deviceItemVo.setProductId(0);
                }
                deviceItemVoList.add(deviceItemVo);
            }
            deviceItemVoList = deviceItemVoList.stream().sorted(Comparator.comparing(DeviceItemVo::getHierarchy)).collect(Collectors.toList());
            deviceVo.setDeviceItemVoList(deviceItemVoList);

            if (DeviceTypeEnum.GASHAPON_MACHINE.getCode().equals(deviceVo.getDeviceTypeId())
                    || DeviceTypeEnum.ONE_TO_MANY_BOXES.getCode().equals(deviceVo.getDeviceTypeId())
            ) {
                DisplayRackItemDto displayRackItemDto = new DisplayRackItemDto();
                displayRackItemDto.setDeviceId(deviceVo.getId());
                displayRackItemDto.setIsDelete(false);
                List<DisplayRackItemVo> displayRackItemVoList = displayRackItemService.findDisplayRackItemByDeviceId(displayRackItemDto);
                deviceVo.setDisplayRackItemVoList(displayRackItemVoList);
            }
        }

        return new PageInfo(deviceVoList);
    }

    /**
     * 解绑设备
     *
     * @param deviceDto
     * @return
     */
    @Override
    public ServerResponse unBindingDevice(DeviceDto deviceDto) {
        if (StringUtils.isEmpty(deviceDto.getId())) {
            return ServerResponse.createByErrorMessage("缺少参数");
        }

        DeviceVo deviceVo = deviceDao.findOneDeviceByDeviceNoAndPermission(deviceDto);
        if (StringUtils.isEmpty(deviceVo)) {
            return ServerResponse.createByErrorMessage("找不到设备");
        }

        deviceDto.setDeviceNo(deviceVo.getDeviceNo());
        if (StringUtils.isEmpty(deviceVo.getMerchantStoreId()) || "-1".equals(deviceVo.getMerchantStoreId())) {
            return ServerResponse.createByErrorMessage("该设备已解绑，请勿重复操作");
        }

        MerchantStore merchantStore = new MerchantStore();
        merchantStore.setId(deviceVo.getMerchantStoreId());
        merchantStore.setUserId(deviceVo.getUserId());
        MerchantStoreVo merchantStoreVo = merchantStoreService.findMerchantStoreByUserIdByStoreId(merchantStore);
        if (StringUtils.isEmpty(merchantStoreVo)) {
            return ServerResponse.createByErrorMessage("在该用户下找不到设备对应的店铺！");
        }


        DeviceDto deviceDtoUpdate = new DeviceDto();
        deviceDtoUpdate.setId(deviceDto.getId());
        deviceDtoUpdate.setAlias(-1);
        deviceDtoUpdate.setMerchantStoreId(-1);
        deviceDtoUpdate.setDeviceTypeId(-1);
        deviceDtoUpdate.setProductId(-1);
        deviceDtoUpdate.setStatus(DeviceStatusEnum.UNBIND.getCode());
        deviceDtoUpdate.setGoodsId(-1L);
        deviceDtoUpdate.setAgreementVersion(-1);
        deviceDtoUpdate.setRateEach(1);
        deviceDtoUpdate.setFaultCode(-1);
        SystemConfig systemConfig = systemConfigService.findOneSystemConfigById(1);
        if (!StringUtils.isEmpty(systemConfig.getUnbindSum())) {
            String key = String.format(RedisKey.UNBIND_SUM, deviceVo.getId());
            Integer unbindSum = (Integer) redisCacheTemplate.opsForValue().get(key);
            if (unbindSum != null && systemConfig.getUnbindSum() <= unbindSum) {
                return ServerResponse.createByErrorMessage("每天设备解绑次数有限，如需继续解绑请明天再解绑");
            }
        }


        Integer count = deviceDao.updateDeviceById(deviceDtoUpdate);
        if (count > 0) {
            // 重置备注名称
            DeviceDto remarkNameDeviceDto = new DeviceDto();
            remarkNameDeviceDto.setId(deviceDto.getId());
            remarkNameDeviceDto.setRemarkName(null);
            deviceDao.updateDeviceRemarkNameById(remarkNameDeviceDto);

            // 安卓设备需要发 信息变动 信号
            if (
                    deviceVo.getNetworkIntensity().compareTo(0) == 1
                            && (
                            deviceVo.getIsAndroid()
                                    || deviceVo.getIsDepositCoinsAndBills()
                                    || deviceVo.getIsGate()
                                    || deviceVo.getIsVendmach()
                    )
            ) {
                // 安卓设备需要发 信息变动 信号
                deviceVo.setMqttMessageBusinessId(SnowflakeIdWorker.nextId());
                this.boundDeviceOrUnBindOrEditDiscountPackage(deviceVo);
            }

            // 控制解绑次数
            if (!StringUtils.isEmpty(systemConfig.getUnbindSum())) {
                Calendar calendar = Calendar.getInstance();
                calendar.add(Calendar.DAY_OF_MONTH, 1);//将日加1
                calendar.set(Calendar.HOUR_OF_DAY, 0);//控制时
                calendar.set(Calendar.MINUTE, 0);//控制分
                calendar.set(Calendar.SECOND, 0);//控制秒
                calendar.set(Calendar.MILLISECOND, 0);//毫秒
                Calendar currentDate = Calendar.getInstance();
                //通过以上操作就得到了一个currentDate明天的0时0分0秒的Calendar对象，然后相减即可得到到明天0时0点0分0秒的时间差
                Integer seconds = (int) ((calendar.getTime().getTime() - currentDate.getTime().getTime()) / 1000);
                String key = String.format(RedisKey.UNBIND_SUM, deviceVo.getId());
                Integer unbindSum = (Integer) redisCacheTemplate.opsForValue().get(key);
                if (unbindSum == null) {
                    redisCacheTemplate.opsForValue().set(key, 1, seconds, TimeUnit.SECONDS);
                } else {
                    redisCacheTemplate.opsForValue().set(key, unbindSum + 1, seconds, TimeUnit.SECONDS);
                }
            }
//            this.updateBinding(0, deviceVo.getNcetId());

            //售货机绑定的商品下架
            if (
                    deviceVo.getDeviceTypeId().equals(DeviceTypeEnum.VENDING_MACHINE.getCode())
                            || deviceVo.getDeviceTypeId().equals(DeviceTypeEnum.SCREEN_VENDING_MACHINE.getCode())
                            || deviceVo.getDeviceTypeId().equals(DeviceTypeEnum.OPEN_DOOR_VENDING_MACHINE.getCode())
                            || deviceVo.getDeviceTypeId().equals(DeviceTypeEnum.GASHAPON_MACHINE.getCode())
            ) {
                log.info("售货机、扭蛋机绑定的商品下架");
                CommodityStoreUpDownDto commodityStoreUpDownDto = new CommodityStoreUpDownDto();
                commodityStoreUpDownDto.setStatus(CommodityStoreUpDownEnum.OFF_SHELF.getCode());
                commodityStoreUpDownDto.setDeviceId(deviceVo.getId());
                commodityStoreUpDownService.updateOffTheShelvesById(commodityStoreUpDownDto);
                if (!ObjectUtils.isEmpty(deviceVo.getIsVendmach())
                        && deviceVo.getIsVendmach()) {
                    String command = PositiveDataFrameCMD.penetrate(HuiLianDuiBiJiPositiveDataFrameCMD.boundDeviceOrUnBindOrEditDiscountPackage());
                    log.info("安卓设备需要发 信息变动 信号command:" + command);
                    boolean pub = pubService.pub(command, deviceVo.getDeviceNo(), productKey);
                }
            }

            // 删除仓位，售货机不删除
            if (
                    !deviceVo.getDeviceTypeId().equals(DeviceTypeEnum.VENDING_MACHINE.getCode())
                            && !deviceVo.getDeviceTypeId().equals(DeviceTypeEnum.SCREEN_VENDING_MACHINE.getCode())
                            && !deviceVo.getDeviceTypeId().equals(DeviceTypeEnum.OPEN_DOOR_VENDING_MACHINE.getCode())
            ) {
                //解绑礼品
                log.info("删除仓位记录");
                DisplayRack updateDisplayRack = new DisplayRack();
                updateDisplayRack.setIsDelete(true);
                updateDisplayRack.setDeviceId(deviceVo.getId());
                updateDisplayRack.setMerchantStoreId(deviceVo.getMerchantStoreId());
                Integer results = displayRackService.update(updateDisplayRack);
            }
            return ServerResponse.createBySuccess();
        } else {
            return ServerResponse.createBySuccess("解绑失败，请联系平台客服处理");
        }
    }

    /**
     * 安卓设备需要发 信息变动 信号
     *
     * @param deviceVo
     */
    @Override
    public void boundDeviceOrUnBindOrEditDiscountPackage(final DeviceVo deviceVo) {
        // 超级兑币机才需要发 信息变动 信号
        String command = PositiveDataFrameCMD.penetrate(HuiLianDuiBiJiPositiveDataFrameCMD.boundDeviceOrUnBindOrEditDiscountPackage());

        log.info("安卓设备需要发 信息变动 信号command:" + command);
        boolean pub = pubService.pub(command, deviceVo.getDeviceNo(), productKey);
        if (!pub) {
            // 发送失败重发
            pubService.pub(command, deviceVo.getDeviceNo(), productKey);
        }

        // 保存发送标识，回复时取出是否接口成功
        final String key = String.format(RedisKey.MQTT_MESSAGE_NUMBER, deviceVo.getId(), IotBoxCmdEnum.D115.getCmdId(), deviceVo.getMqttMessageBusinessId());
        log.info("key:" + key);
        redisCacheTemplate.opsForValue().set(key, -1, 10, TimeUnit.SECONDS);
    }


    @Override
    public ServerResponse findResidueNewDeviceToDay(DeviceDto deviceDto) {
        // 每天最大生成的数量
        int maxNumber = 9999;

        Device device = deviceDao.findResidueNewDeviceToDay();

        // 20210424
        String deviceNoYMD = LocalDate.now().toString().replaceAll("-", "");

        String nowDeviceNoYMD = device.getDeviceNo().toString().substring(0, 8);

        NewDeviceVo newDeviceVo = new NewDeviceVo();
        if (nowDeviceNoYMD.equals(deviceNoYMD)) {
            // 如果是今天的
            String nowDeviceNo = device.getDeviceNo().toString().substring(8);
            int nowDeviceNum = Integer.parseInt(nowDeviceNo);
            // 剩余数量
            int residueNewDeviceNumber = maxNumber - nowDeviceNum;

            newDeviceVo.setNewDeviceNumber(residueNewDeviceNumber);
            newDeviceVo.setDeviceNoYMD(nowDeviceNoYMD);

            if (residueNewDeviceNumber == 0) {
                // 当剩余数量为0时默认0001开始
                newDeviceVo.setBeginNo(String.format("%04d", 1));
            } else {
                newDeviceVo.setBeginNo(String.format("%04d", nowDeviceNum + 1));
            }

            newDeviceVo.setEndNo("9999");
            return ServerResponse.createBySuccess(newDeviceVo);
        }

        newDeviceVo.setNewDeviceNumber(9999);
        newDeviceVo.setDeviceNoYMD(deviceNoYMD);
        newDeviceVo.setBeginNo(String.format("%04d", 1));
        newDeviceVo.setEndNo("9999");

        return ServerResponse.createBySuccess(newDeviceVo);
    }

    @Override
    public DeviceVo findDeviceStatistic(DeviceDto deviceDto) {
        return deviceDao.findDeviceStatistic(deviceDto);
    }

    @Override
    public DeviceVo findNewDeviceCount(DeviceDto deviceDto) {
        return deviceDao.findNewDeviceCount(deviceDto);
    }

    @Override
    public Integer findSetDeviceNoTrade(Integer agencyId, Set<String> set) {
        return deviceDao.findSetDeviceNoTrade(agencyId, set);
    }

    /**
     * 根据设备号范围查分配设备
     *
     * @param deviceDto
     * @return
     */
    @Override
    public List<DeviceVo> findDistributionDevice(DeviceDto deviceDto) {
        deviceDto.setStartDevice(deviceDto.getStartDevice().trim());
        deviceDto.setEndDevice(deviceDto.getEndDevice().trim());
        PageHelper.startPage(deviceDto.getPageNum(), deviceDto.getPageSize());
        List<DeviceVo> deviceVoList = deviceDao.findDistributionDevice(deviceDto);
        return deviceVoList;
    }

    /**
     * 分配设备
     *
     * @param deviceDto
     * @return
     */
    @Override
    public ServerResponse distributionDevice(DeviceDto deviceDto) {
        // 防止参数为空
        if (StringUtils.isEmpty(deviceDto.getIsAnew())) {
            deviceDto.setIsAnew(0);
        }

        // 只有超级管理员才能重新分配已分配的设备
        if (1 == deviceDto.getIsAnew() && deviceDto.getUserInfo().getRoleId() != RoleEnum.SUPER_ADMINISTRATOR.getRoleId()) {
            return ServerResponse.createByErrorMessage("重新分配权限不足！");
        }

        deviceDto.setStartDevice(deviceDto.getStartDevice().trim());
        deviceDto.setEndDevice(deviceDto.getEndDevice().trim());
        List<DeviceVo> deviceVoList = deviceDao.findDistributionDevice(deviceDto);
        DeviceVo device = new DeviceVo();
        Integer succeed = 0;
        Integer fail = 0;
        List<DeviceVo> distributionFailList = new ArrayList<>();
        List<DeviceVo> distributionSuccessList = new ArrayList<>();
        for (DeviceVo deviceVo : deviceVoList) {
            DeviceVo dataFail = new DeviceVo();

            if (1 == deviceDto.getIsAnew()) {
                // 重新分配
                /**
                 * 没绑定门店
                 */
                if (!StringUtils.isEmpty(deviceVo.getMerchantStoreId()) && deviceVo.getMerchantStoreId() > 0) {
                    dataFail.setDeviceNo(deviceVo.getDeviceNo());
                    dataFail.setFailReason("设备已绑定运营商，无法移动！");
                    dataFail.setStatus(deviceVo.getStatus());
                    dataFail.setAgencyName(deviceVo.getAgencyName());
                    distributionFailList.add(dataFail);
                    fail++;
                } else {
                    deviceVo.setAgencyId(deviceDto.getAgencyId());
                    if (!StringUtils.isEmpty(deviceDto.getSyntheticType())) {
                        deviceVo.setIsAndroid(false);
                        deviceVo.setIsVendmach(false);
                        deviceVo.setIsGate(false);
                        deviceVo.setIsDepositCoinsAndBills(false);
                        deviceVo.setIsBluetooth(false);
                        if (!StringUtils.isEmpty(deviceDto.getSyntheticType())) {
                            if (deviceDto.getSyntheticType() == 1) {
                                deviceVo.setIsAndroid(true);
                            } else if (deviceDto.getSyntheticType() == 2) {
                                deviceVo.setIsVendmach(true);
                            } else if (deviceDto.getSyntheticType() == 3) {
                                deviceVo.setIsGate(true);
                            } else if (deviceDto.getSyntheticType() == 4) {
                                deviceVo.setIsDepositCoinsAndBills(true);
                            } else if (deviceDto.getSyntheticType() == 5) {
                                deviceVo.setIsBluetooth(true);
                                deviceVo.setServiceProvider(2);
                            }
                        }
                    }
                    distributionSuccessList.add(deviceVo);
                    succeed++;
                }
            } else {
                // 新分配
                /**
                 * 机构id是自己
                 * 没绑定门店
                 */
                if (deviceDto.getUserInfo().getAgencyId().equals(deviceVo.getAgencyId()) && (StringUtils.isEmpty(deviceVo.getMerchantStoreId()) || deviceVo.getMerchantStoreId() == -1)) {
                    deviceVo.setAgencyId(deviceDto.getAgencyId());
                    deviceVo.setIsAndroid(false);
                    deviceVo.setIsVendmach(false);
                    deviceVo.setIsGate(false);
                    deviceVo.setIsDepositCoinsAndBills(false);
                    deviceVo.setIsBluetooth(false);
                    if (!StringUtils.isEmpty(deviceDto.getSyntheticType())) {
                        if (deviceDto.getSyntheticType() == 1) {
                            deviceVo.setIsAndroid(true);
                        } else if (deviceDto.getSyntheticType() == 2) {
                            deviceVo.setIsVendmach(true);
                        } else if (deviceDto.getSyntheticType() == 3) {
                            deviceVo.setIsGate(true);
                        } else if (deviceDto.getSyntheticType() == 4) {
                            deviceVo.setIsDepositCoinsAndBills(true);
                        } else if (deviceDto.getSyntheticType() == 5) {
                            deviceVo.setIsBluetooth(true);
                            deviceVo.setServiceProvider(2);
                        }
                    }
                    distributionSuccessList.add(deviceVo);
                    succeed++;
                } else {
                    dataFail.setDeviceNo(deviceVo.getDeviceNo());
                    dataFail.setFailReason("设备已绑定运营商，无法移动！");
                    dataFail.setStatus(deviceVo.getStatus());
                    dataFail.setAgencyName(deviceVo.getAgencyName());
                    dataFail.setRebateAgencyName(deviceVo.getRebateAgencyName());
                    distributionFailList.add(dataFail);
                    fail++;
                }
            }
        }

        if (distributionSuccessList.size() > 0) {
            deviceDao.updateDeviceByIdToList(distributionSuccessList);
        }

        device.setDistributionFailList(distributionFailList);
        device.setDistributionSucceedCount(succeed);
        device.setDistributionFailCount(fail);
        return ServerResponse.createBySuccess(device);
    }

    @Override
    public ServerResponse updateDeviceById(DeviceDto deviceDto) {
        return ServerResponse.createBySuccess(deviceDao.updateDeviceById(deviceDto));
    }

    @Override
    public ServerResponse updateUnbindSum(DeviceDto deviceDto) {
        String key = String.format(RedisKey.UNBIND_SUM, deviceDto.getId());
        redisCacheTemplate.delete(key);
        return ServerResponse.createBySuccess();
    }

    /**
     * 发送修改盒子配置
     *
     * @param deviceDto
     * @return
     */
    @Override
    public ServerResponse sendUpdateBoxConfigById(DeviceDto deviceDto) {
        if (StringUtils.isEmpty(deviceDto.getId()) || StringUtils.isEmpty(deviceDto.getBaudId())) {
            return ServerResponse.createByErrorMessage("参数id、baudId为空！");
        } else if (StringUtils.isEmpty(deviceDto.getDataBit()) || StringUtils.isEmpty(deviceDto.getLevel())) {
            return ServerResponse.createByErrorMessage("参数数据位、level为空！");
        } else if (StringUtils.isEmpty(deviceDto.getParityBit()) || StringUtils.isEmpty(deviceDto.getStopBit())) {
            return ServerResponse.createByErrorMessage("参数校验位、停止位为空！");
        }

        DeviceVo deviceVo = deviceDao.findOneDeviceById(deviceDto.getUserInfo(), deviceDto.getId());
        if (StringUtils.isEmpty(deviceVo)) {
            return ServerResponse.createByErrorMessage(ErrorMsgEnum.DEVICE_NOT_FOUND.getMsg());
        }

        if (deviceVo.getNetworkIntensity() <= 0) {
            return ServerResponse.createByErrorMessage(ErrorMsgEnum.INSERT_COIN_FAIL_BY_NO_NETWORK.getMsg());
        }

        Baud baudCondition = new Baud();
        baudCondition.setId(deviceDto.getBaudId());
        Baud baud = baudService.findOneBaudByCondition(baudCondition);

        String tcp = null;
        if (!deviceDto.getLevel().equals(deviceVo.getLevel())) {
            // 修改常开常闭
            tcp = PositiveDataFrameCMD.setOutwardCoinLevel(IotBoxUtil.singleInt2Hex(deviceDto.getLevel()));
            log.info("tcp:" + tcp);
            pubService.pub(tcp, deviceVo.getDeviceNo(), productKey);
        }

        if (!deviceDto.getPulseSwitchState().equals(deviceVo.getPulseSwitchState()) || !deviceDto.getBaudId().equals(deviceVo.getBaudId())) {
            // 修改波特率、数据位、校验位、停止位、脉冲功能开关
            tcp = PositiveDataFrameCMD.setSerialPort(baud.getCode(), deviceDto.getDataBit(), deviceDto.getParityBit(), deviceDto.getStopBit(), deviceDto.getPulseSwitchState());

            log.info("修改波特率、数据位、校验位、停止位、脉冲功能开关tcp:" + tcp);
            pubService.pub(tcp, deviceVo.getDeviceNo(), productKey);
        } else if (!deviceDto.getDataBit().equals(deviceVo.getDataBit()) || !deviceDto.getParityBit().equals(deviceVo.getParityBit())) {
            // 修改波特率、数据位、校验位、停止位、脉冲功能开关
            tcp = PositiveDataFrameCMD.setSerialPort(baud.getCode(), deviceDto.getDataBit(), deviceDto.getParityBit(), deviceDto.getStopBit(), deviceDto.getPulseSwitchState());
            log.info("修改波特率、数据位、校验位、停止位、脉冲功能开关tcp:" + tcp);
            pubService.pub(tcp, deviceVo.getDeviceNo(), productKey);
        } else if (!deviceDto.getStopBit().equals(deviceVo.getStopBit())) {
            // 修改波特率、数据位、校验位、停止位、脉冲功能开关
            tcp = PositiveDataFrameCMD.setSerialPort(baud.getCode(), deviceDto.getDataBit(), deviceDto.getParityBit(), deviceDto.getStopBit(), deviceDto.getPulseSwitchState());
            log.info("修改波特率、数据位、校验位、停止位、脉冲功能开关tcp:" + tcp);
            pubService.pub(tcp, deviceVo.getDeviceNo(), productKey);
        }

        // 延迟去查它的参数
        Map<String, String> delayMap = new HashMap<>();
        delayMap.put("code", CompositeDelayQueueEnum.INITIATIVE_SEND_QUERY_BASE_PARAMS.getCode());
        delayMap.put("deviceNo", deviceVo.getDeviceNo());
        rabbitProducer.sendReplayLazyQueue(delayMap, 2000);

        return ServerResponse.createBySuccess();
    }

    @Override
    public List<Device> findAllDeviceByCondition(DeviceDto deviceDto) {
        return deviceDao.findAllDeviceByCondition(deviceDto);
    }

    /**
     * 发送修改盒子脉冲
     *
     * @param deviceDto
     * @return
     */
    @Override
    public ServerResponse sendUpdateBoxConfigPulse(DeviceDto deviceDto) {

        if (StringUtils.isEmpty(deviceDto.getId()) || StringUtils.isEmpty(deviceDto.getHeartbeatTime())) {
            return ServerResponse.createByErrorMessage("参数id、心跳时间不能为空");
        }
        if (StringUtils.isEmpty(deviceDto.getGapLength()) || StringUtils.isEmpty(deviceDto.getPulseLength()) || StringUtils.isEmpty(deviceDto.getRitualModel())) {
            return ServerResponse.createByErrorMessage("参数投币脉冲间隔宽度、出礼模式不能为空");
        }
        if (StringUtils.isEmpty(deviceDto.getId()) || StringUtils.isEmpty(deviceDto.getHeartbeatTime())) {
            return ServerResponse.createByErrorMessage("出礼脉冲间隔、长度不能为空");
        }

        DeviceVo deviceVo = deviceDao.findOneDeviceById(deviceDto.getUserInfo(), deviceDto.getId());
        if (StringUtils.isEmpty(deviceVo)) {
            return ServerResponse.createByErrorMessage(ErrorMsgEnum.DEVICE_NOT_FOUND.getMsg());
        }

        if (deviceVo.getNetworkIntensity() <= 0) {
            return ServerResponse.createByErrorMessage(ErrorMsgEnum.INSERT_COIN_FAIL_BY_NO_NETWORK.getMsg());
        }

        String tcp = PositiveDataFrameCMD.setPulse(deviceDto.getHeartbeatTime(), deviceDto.getGapLength(), deviceDto.getPulseLength(), deviceDto.getRitualModel(), deviceDto.getOutgoingGapLength(), deviceDto.getOutgoingPulseLength());
        log.info("tcp:" + tcp);
        pubService.pub(tcp, deviceVo.getDeviceNo(), productKey);

        // 延迟去查它的参数
        Map<String, String> delayMap = new HashMap<>();
        delayMap.put("code", CompositeDelayQueueEnum.INITIATIVE_SEND_QUERY_BASE_PARAMS.getCode());
        delayMap.put("deviceNo", deviceVo.getDeviceNo());
        rabbitProducer.sendReplayLazyQueue(delayMap, 2000);

        return ServerResponse.createBySuccess();
    }

    @Override
    public List<DeviceVo> findAllDeviceByNoHeart(int time) {
        return deviceDao.findAllDeviceByNoHeart(time);
    }

    @Override
    public List<DeviceVo> findDeviceAll(String heartbeatTime) {
        return deviceDao.findDeviceAll(heartbeatTime);
    }

    @Override
    public Integer insert(Device device) {
        return deviceDao.insert(device);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ServerResponse batchRegisterDevice(DeviceDto deviceDto) {

        if (!RoleEnum.SUPER_ADMINISTRATOR.getRoleId().equals(deviceDto.getUserInfo().getRoleId())) {
            return ServerResponse.createByError("无权限添加设备");
        }

        if (StringUtils.isEmpty(deviceDto.getStartNo())) {
            return ServerResponse.createByError("请输入新增设备的开始号段");
        }

        if (StringUtils.isEmpty(deviceDto.getEndNo())) {
            return ServerResponse.createByError("请输入新增设备的结束号段");
        }

        Long startNoL = Long.parseLong(deviceDto.getStartNo());
        Long endNoL = Long.parseLong(deviceDto.getEndNo());

        if (startNoL.compareTo(endNoL) > 0) {
            return ServerResponse.createByError("开始号段必须小于等于结束号段");
        }

        Long count = endNoL - startNoL + 1L;
        System.out.println("count:" + count);
        if (count <= 0) {
            return ServerResponse.createByErrorMessage("区间设备数量不能为0");
        }

        if (count > 500) {
            return ServerResponse.createByErrorMessage("一次性添加的设备数量最多为500个");
        }

        List<DeviceVo> deviceVos = deviceDao.findSectionDeviceNo(deviceDto.getStartNo(), deviceDto.getEndNo());
        Map<String, DeviceVo> deviceVoMap = deviceVos.stream().collect(Collectors.toMap(DeviceVo::getDeviceNo, a -> a, (k1, k2) -> k1));

        Device device = new Device();
        device.setAgencyId(1);
        device.setNetworkIntensity(0);
        device.setRateEach(1);
        device.setStatus(DeviceStatusEnum.NON_ACTIVATED.getCode());
        device.setVendorId(3);
        device.setServiceProvider(DeviceServiceProviderEnum.EMQX.getCode());

        int newAdd = 0;
        for (Long i = startNoL; i <= endNoL; i++) {
            final String deviceNo = String.valueOf(i);
            DeviceVo deviceVo = deviceVoMap.get(deviceNo);
            if (!StringUtils.isEmpty(deviceVo)) {
                continue;
            }

            device.setDeviceNo(deviceNo);
            device.setPassword(UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32).toLowerCase());
            deviceDao.insert(device);
            newAdd++;
            System.out.println(deviceNo);
        }

        if (newAdd == 0) {
            return ServerResponse.createByErrorMessage("添加失败，区间设备" + deviceDto.getStartNo() + "-" + deviceDto.getEndNo() + "已存在，请勿重复添加");
        }

        return ServerResponse.createBySuccess("成功添加" + newAdd + "个设备");
    }

    @Override
    public ServerResponse clearDebugConsumeSum(DeviceDto deviceDto) {

        if (StringUtils.isEmpty(deviceDto.getDeviceNo())) {
            return ServerResponse.createByErrorMessage("设备号不能为空");
        }

        String key = String.format(RedisKey.DEBUG_CONSUME_SUM, deviceDto.getDeviceNo());
        redisCacheTemplate.delete(key);
        return ServerResponse.createBySuccess();
    }

    @Override
    @Transactional
    public ServerResponse clearFreightLane(DeviceDto deviceDto) {
        if (StringUtils.isEmpty(deviceDto.getDeviceNo())) {
            return ServerResponse.createByErrorMessage("设备号不能为空");
        }
        DeviceVo deviceVo = deviceDao.findDeviceByDeviceNo(deviceDto.getDeviceNo());
        DisplayRack displayRack = displayRackService.findDisplayByDeviceId(deviceVo.getId());
        if (ObjectUtils.isEmpty(displayRack)) {
            return ServerResponse.createByErrorMessage("该设备无货道信息，无需清除");
        }
        if (!ObjectUtils.isEmpty(deviceVo)) {
            DisplayRack newDisplayRack = new DisplayRack();
            newDisplayRack.setId(displayRack.getId());
            newDisplayRack.setIsDelete(true);
            int result = displayRackService.updateIsDelete(newDisplayRack);
            if (result != 1) {
                return ServerResponse.createByErrorMessage("清除失败");
            }
            return ServerResponse.createBySuccess();
        } else {
            return ServerResponse.createByErrorMessage("找不到该设备");
        }

    }

    @Override
    @Transactional
    public ServerResponse updateMaintainDevice(DeviceDto deviceDto) {
        SystemConfig systemConfig = systemConfigService.findOneSystemConfigById(1);
        if (!systemConfig.getNetCardIsOpen()) {
            return ServerResponse.createByErrorMessage("网卡功能已关闭！");
        }

        deviceDto.setStatus(DeviceStatusEnum.MAINTAIN.getCode());
        DeviceVo deviceVo = deviceDao.findOneDeviceById(deviceDto.getUserInfo(), deviceDto.getId());
        if (StringUtils.isEmpty(deviceDto.getNewDeviceNo())) {
            if (deviceVo.getNcetId() != 0 && deviceVo.getNcetId() != null) {
                deviceDto.setNetCardReplaceStatus(NetCardReplaceStatusEnum.NOT_REPLACE.getCode());
            }
            return ServerResponse.createBySuccess(deviceDao.updateDeviceById(deviceDto));
        } else {
            // 查询新设备状态是否正常
            DeviceVo item = deviceDao.findDeviceByDeviceNo(deviceDto.getNewDeviceNo());
            if (StringUtils.isEmpty(item)) {
                return ServerResponse.createByErrorMessage("您输入的设备号有误，请重新输入");
            }
            if (!item.getAgencyId().equals(deviceVo.getAgencyId())) {
                return ServerResponse.createByErrorMessage("新旧设备不在同一个机构下，替换失败");
            }
            if (DeviceStatusEnum.MAINTAIN.getCode().equals(item.getStatus())) {
                return ServerResponse.createByErrorMessage("新设备处于" + DeviceStatusEnum.MAINTAIN.getDesc() + "中无法替换网卡");
            }
            if (item.getNcetId() != null) {
                deviceDto.setNcetId(item.getNcetId());
            } else {
                deviceDto.setNcetId(0);
            }
            // 替换网卡
            deviceDto.setNetCardReplaceStatus(NetCardReplaceStatusEnum.REPLACE.getCode());
            Integer count = deviceDao.updateDeviceById(deviceDto);
            if (count > 0) {
                if (deviceVo.getNcetId() == 0 || deviceVo.getNcetId() == null) {
                    return ServerResponse.createByErrorMessage("该设备未绑定网卡无需替换");
                }
                Device device = new Device();
                device.setNcetId(deviceVo.getNcetId());
                device.setDeviceNo(deviceDto.getNewDeviceNo());
                deviceDao.updateDeviceByDeviceNo(device);
                return ServerResponse.createBySuccess();
            } else {
                return ServerResponse.createByErrorMessage("修改设备状态失败");
            }

        }
    }


    /**
     * 请勿调用该sql,否则你会体验飞翔的感觉
     */
    @Override
    public Integer updateDeviceTotalTransactionAmount(DeviceVo deviceVo) {
        return deviceDao.updateDeviceTotalTransactionAmount(deviceVo);
    }

    /**
     * 超级兑币机动态注册设备号
     *
     * @param deviceDto
     * @param request
     * @return
     */
    @Override
    public synchronized ServerResponse registerDevice(DeviceDto deviceDto, HttpServletRequest request) throws IOException, NoSuchAlgorithmException, ClientException {

        if (StringUtils.isEmpty(deviceDto.getTimestamp())) {
            return ServerResponse.createByErrorMessage("timestamp不能为空");
        }

//        Long timeMillis = System.currentTimeMillis();
//        Long m = (timeMillis - deviceDto.getTimestamp()) / 1000 / 60;
//        if (m >= 10) {
//            return ServerResponse.createByErrorMessage("timestamp已过期");
//        }

        if (StringUtils.isEmpty(deviceDto.getSign())) {
            return ServerResponse.createByErrorMessage("sign不能为空");
        }

        Map<String, Object> inParams = new HashMap<>();
        inParams.put("timestamp", deviceDto.getTimestamp());

        String checkSign = MD5SignUtil.signTopRequestByMap(inParams, MD5SignUtil.secret);
        if (!deviceDto.getSign().equalsIgnoreCase(checkSign)) {
            return ServerResponse.createByErrorMessage("校验不通过");
        }

        String start = deviceDao.findDeviceNoMax();
        if (StringUtils.isEmpty(start)) {
            return ServerResponse.createByError("请初始化设备");
        }
        String prefix = start.substring(0, 1);
        start = start.substring(1);
        int startInt = Integer.parseInt(start);

        startInt++;
        final String subfix = String.valueOf(startInt);
        StrBuilder zero = new StrBuilder();
        for (int i1 = 0; i1 < 5 - subfix.length(); i1++) {
            zero.append("0");
        }
        zero.append(subfix);
        String newDeviceNo = prefix + zero;

        // 到阿里云注册设备
        RegisterDeviceResponse response = DeviceManager.registerDevice(iotInstanceId, productKey, newDeviceNo);
        log.info(JSON.toJSONString(response));
        /**
         * {
         *   "code": "iot.device.AlreadyExistedDeviceName",
         *   "data": {
         *
         *   },
         *   "errorMessage": "The device already exists.",
         *   "requestId": "CD8DE2E0-41C6-56FF-92B9-B1039A16818B",
         *   "success": false
         * }
         *
         * {
         *   "code": "",
         *   "data": {
         *     "deviceName": "901002",
         *     "deviceSecret": "7c51cfdc9c*******017b98d8",
         *     "iotId": "eJOXit********Rgfah07",
         *     "joinEui": "",
         *     "productKey": "gfa****IiI"
         *   },
         *   "requestId": "B21751*********91F4",
         *   "success": true
         * }
         */
        if (response.getSuccess() != null && response.getSuccess()) {
            log.info("注册设备成功");
            log.info(JSON.toJSONString(response));
        } else {
            log.error("注册设备失败");
            log.error(JSON.toJSONString(response));
            return ServerResponse.createByErrorMessage("注册设备失败");
        }

        Device device = new Device();
        device.setAgencyId(1);
        device.setNetworkIntensity(0);
        device.setRateEach(1);
        device.setStatus(DeviceStatusEnum.NON_ACTIVATED.getCode());
        device.setPulseSwitchState(false);
        device.setVendorId(3);
        device.setDeviceNo(newDeviceNo);
        deviceDao.insert(device);

        RegisterDeviceResponse.Data data = response.getData();
        String productKeySign = KaiSaEncrypt.encryptKaiser(data.getProductKey());
        String secretSign = KaiSaEncrypt.encryptKaiser(data.getDeviceSecret());

        Map<String, Object> params = new HashMap<>();
        params.put("productKey", productKeySign);
        params.put("deviceName", newDeviceNo);
        params.put("deviceSecret", secretSign);
        String sign = MD5SignUtil.signTopRequestByMap(params, MD5SignUtil.secret);
        params.put("sign", sign);

        System.out.println(JSON.toJSONString(params));
        return ServerResponse.createBySuccess(params);
    }

    /**
     * 恢复出厂状态
     *
     * @param deviceDto
     * @return
     */
    @Override
    public ServerResponse restoreFactoryDefault(DeviceDto deviceDto) {

        // 只有“只有解绑状态才可以恢复出厂状态”
        if (StringUtils.isEmpty(deviceDto.getId())) {
            return ServerResponse.createByErrorMessage("设备ID不能为空");
        }

        DeviceVo deviceVo = deviceDao.findOneDeviceById(deviceDto.getUserInfo(), deviceDto.getId());
        if (StringUtils.isEmpty(deviceVo)) {
            return ServerResponse.createByErrorMessage("设备不存在");
        }

        DeviceDto updateDevice = new DeviceDto();
        updateDevice.setId(deviceDto.getId());
        updateDevice.setStatus(DeviceStatusEnum.NON_ACTIVATED.getCode());
        updateDevice.setMerchantStoreId(0);
        int row = deviceDao.updateDeviceById(updateDevice);

        if (row == 0) {
            return ServerResponse.createByErrorMessage("请重试");
        }
        return ServerResponse.createBySuccess();
    }

    /**
     * 根据ID查询设备信息
     *
     * @param deviceDto
     * @return
     */
    @Override
    public DeviceVo findOneDeviceById(DeviceDto deviceDto) {

        DeviceVo deviceVo = deviceDao.findOneDeviceById(deviceDto.getUserInfo(), deviceDto.getId());
        if (StringUtils.isEmpty(deviceVo)) {
            throw new RuntimeException("设备不存在");
        }

        return deviceVo;
    }

    /**
     * 发送调试协议
     *
     * @param deviceDto
     * @return
     */
    @Override
    public ServerResponse sendTestCmd(DeviceDto deviceDto) {

        if (StringUtils.isEmpty(deviceDto.getDeviceNo())) {
            return ServerResponse.createByErrorMessage("设备号不能为空");
        }

        if (StringUtils.isEmpty(deviceDto.getCmd())) {
            return ServerResponse.createByErrorMessage("cmd不能为空");
        }

        final String str = deviceDto.getCmd().replaceAll(" ", "");
        log.warn("发送设备：{}", deviceDto.getDeviceNo());
        log.warn("发送内容：{}", str);

        String command = PositiveDataFrameCMD.penetrate(str);
        log.warn("command：{}", command);
        boolean pub = pubService.pub(command, deviceDto.getDeviceNo(), productKey);
        if (!pub) {
            return ServerResponse.createByErrorMessage("发送失败");
        }

        return ServerResponse.createBySuccess();
    }

    /**
     * 兑币机APK根据合作伙伴号自动分配设备号
     *
     * @param deviceDto
     * @return
     */
    @Override
    public synchronized ServerResponse registerDeviceByAgencyNo(DeviceDto deviceDto) throws Exception {

        if (StringUtils.isEmpty(deviceDto.getAgencyNo())) {
            return ServerResponse.createByErrorMessage("agencyNo不能为空");
        }

        if (StringUtils.isEmpty(deviceDto.getCpuId())) {
            return ServerResponse.createByErrorMessage("cpuId不能为空");
        }

        if (StringUtils.isEmpty(deviceDto.getTimestamp())) {
            return ServerResponse.createByErrorMessage("timestamp不能为空");
        }

        if (StringUtils.isEmpty(deviceDto.getSign())) {
            return ServerResponse.createByErrorMessage("sign不能为空");
        }

        Map<String, Object> params = new HashMap<>();
        params.put("agencyNo", deviceDto.getAgencyNo());
        params.put("cpuId", deviceDto.getCpuId());
        params.put("androidMotherboardModel", deviceDto.getAndroidMotherboardModel());
        params.put("timestamp", deviceDto.getTimestamp());

        // 兼容部分兑币机使用版本过低的（版本低的没有上报这个字段）
        if (!StringUtils.isEmpty(deviceDto.getDeviceRegisterType())) {
            params.put("deviceRegisterType", deviceDto.getDeviceRegisterType());
        } else {
            deviceDto.setDeviceRegisterType(DeviceRegisterTypeEnum.SUPER_MONEY_CHANGER.getCode());
        }

        String checkSign = MD5SignUtil.signTopRequestByMap(params, MD5SignUtil.secret);
        if (!deviceDto.getSign().equalsIgnoreCase(checkSign)) {
            return ServerResponse.createByErrorMessage("校验不通过");
        }

        log.warn("deviceDto：{}", JSON.toJSONString(deviceDto));

        DeviceDto dto = new DeviceDto();
        dto.setCpuId(deviceDto.getCpuId());
        // 根据cpuId查询
        DeviceVo deviceVo = deviceDao.findOneDeviceByCondition(dto);
        if (StringUtils.isEmpty(deviceVo)) {
            dto.setStatus(DeviceStatusEnum.NON_ACTIVATED.getCode());
            dto.setAgencyNo(deviceDto.getAgencyNo());
            if (DeviceRegisterTypeEnum.SUPER_MONEY_CHANGER.getCode().equals(deviceDto.getDeviceRegisterType())) {
                // 超级兑币机分配设备号
                dto.setIsAndroid(true);
            } else if (DeviceRegisterTypeEnum.DEPOSIT_COINS_AND_BILLS.getCode().equals(deviceDto.getDeviceRegisterType())) {
                // 存币存票分配设备号
                dto.setIsDepositCoinsAndBills(true);
            } else if (DeviceRegisterTypeEnum.GATE.getCode().equals(deviceDto.getDeviceRegisterType())) {
                // 门闸分配设备号
                dto.setIsGate(true);
            } else if (DeviceRegisterTypeEnum.VENDMACH.getCode().equals(deviceDto.getDeviceRegisterType())) {
                // 门闸分配设备号
                dto.setIsGate(true);
            } else {
                throw new RuntimeException("deviceRegisterType有误");
            }
            deviceVo = deviceDao.findOneDeviceByNotAllocated(dto);

            if (StringUtils.isEmpty(deviceVo)) {
                return ServerResponse.createByErrorMessage("合作伙伴暂无可分配的设备号");
            }
        }

        ServerResponse deviceInfoCommon = getDeviceInfoCommon(params, deviceVo);
        if (!deviceInfoCommon.getIsSuccess()) {
            return deviceInfoCommon;
        }

        // 设置为已分配
        DeviceDto updateDeviceDto = new DeviceDto();
        updateDeviceDto.setId(deviceVo.getId());
        updateDeviceDto.setCpuId(deviceDto.getCpuId());
        updateDeviceDto.setIsAllocated(true);
        updateDeviceDto.setStatus(DeviceStatusEnum.ON_LINE.getCode());
        deviceDao.updateDeviceById(updateDeviceDto);

        return deviceInfoCommon;
    }

    private ServerResponse getDeviceInfoCommon(Map<String, Object> params, DeviceVo deviceVo) throws Exception {
        // 获取设备秘钥
        DeviceVo device = deviceDao.findOneDevicePwd(deviceVo.getDeviceNo());
        if (StringUtils.isEmpty(device)) {
            return ServerResponse.createByErrorMessage("设备号不存在");
        }
        String productKeySign = KaiSaEncrypt.encryptKaiser(productKey);
        String secretSign = KaiSaEncrypt.encryptKaiser(device.getPassword());

        // 商家超级兑币机头部广告图
        List<MerchantBannerVo> merchantBannerVoList = new ArrayList<>();
        // 商家超级兑币机全屏广告图
        List<MerchantBannerVo> merchantFullScreenBannerVoList = new ArrayList<>();
        // 取客服电话
        String serviceMobilePhone = null;
        String serviceWeChatQr = null;
        if (!StringUtils.isEmpty(deviceVo.getMerchantStoreId()) && deviceVo.getMerchantStoreId().compareTo(0) == 1) {
            CustomerServiceInfo customerServiceInfo = customerServiceInfoService.findOneByMerchantStoreId(deviceVo.getMerchantStoreId());
            if (!StringUtils.isEmpty(customerServiceInfo)) {
                serviceMobilePhone = customerServiceInfo.getServiceMobilePhone();
                serviceWeChatQr = customerServiceInfo.getServiceWeChatQr();
            }

            MerchantBannerDto merchantBannerDto = new MerchantBannerDto();
            merchantBannerDto.setMerchantStoreId(deviceVo.getMerchantStoreId());
            merchantBannerDto.setStatus(1);
            merchantBannerDto.setDeviceId(deviceVo.getId());
            merchantBannerDto.setType(MerchantBannerTypeEnum.TOP_EXCLUSIVE.getCode());
            // 1、先查某场地某兑币机头部专属广告
            List<MerchantBannerVo> merchantBannerVos = merchantBannerService.findAllMerchantBannerByMerchantStoreId(merchantBannerDto);
            if (!StringUtils.isEmpty(merchantBannerVos) && merchantBannerVos.size() > 0) {
                merchantBannerVoList = merchantBannerVos;
            } else if (StringUtils.isEmpty(merchantBannerVos) || merchantBannerVos.size() == 0) {
                // 2、没有某场地某兑币机头部专属广告，就查该兑币机对应的场地头部广告
                merchantBannerDto.setDeviceId(null);
                merchantBannerDto.setType(MerchantBannerTypeEnum.TOP.getCode());
                merchantBannerVos = merchantBannerService.findAllMerchantBannerByMerchantStoreId(merchantBannerDto);

                if (StringUtils.isEmpty(merchantBannerVos) || merchantBannerVos.size() == 0) {
                    // 3、设备专属、场地都没有广告就默认系统的
                    merchantBannerDto.setMerchantStoreId(0);
                    merchantBannerVoList = merchantBannerService.findAllMerchantBannerByMerchantStoreId(merchantBannerDto);
                } else {
                    merchantBannerVoList = merchantBannerVos;
                }
            }

            merchantBannerDto.setMerchantStoreId(deviceVo.getMerchantStoreId());
            merchantBannerDto.setStatus(1);
            merchantBannerDto.setType(MerchantBannerTypeEnum.FULL_EXCLUSIVE.getCode());
            merchantBannerDto.setDeviceId(deviceVo.getId());
            // 查某台兑币机的全屏广告
            merchantFullScreenBannerVoList = merchantBannerService.findAllMerchantBannerByMerchantStoreId(merchantBannerDto);

            if (StringUtils.isEmpty(merchantFullScreenBannerVoList) || merchantFullScreenBannerVoList.size() == 0) {
                merchantBannerDto.setType(MerchantBannerTypeEnum.FULL_SCREEN.getCode());
                merchantBannerDto.setDeviceId(null);
                // 查某场地的兑币机全屏广告
                merchantFullScreenBannerVoList = merchantBannerService.findAllMerchantBannerByMerchantStoreId(merchantBannerDto);
            }
        }


        params.clear();
        params.put("deviceName", deviceVo.getDeviceNo());
        params.put("deviceTypeId", deviceVo.getDeviceTypeId());
        params.put("productKey", productKeySign);
        params.put("deviceSecret", secretSign);
        params.put("merchantStoreId", deviceVo.getMerchantStoreId());
        params.put("serviceMobilePhone", serviceMobilePhone);
        params.put("serviceWeChatQr", serviceWeChatQr);
        params.put("registerUrl", "http://weixin.qq.com/q/02pah3MCxfflD10000w03a");
        // 先默认平台企业微信客户群
        params.put("serviceEnterpriseWeChatGroupQr", "https://work.weixin.qq.com/m/66efa901b5fd01900ee8535dfe8542f6?is=174");
        String sign = MD5SignUtil.signTopRequestByMap(params, MD5SignUtil.secret);
        params.put("sign", sign);

        // 超级兑币机头部广告图
        String[] merchantBannerArray = new String[merchantBannerVoList.size()];
        for (int i = 0; i < merchantBannerVoList.size(); i++) {
            merchantBannerArray[i] = merchantBannerVoList.get(i).getFileName();
        }
        params.put("merchantBannerArray", merchantBannerArray);

        // 超级兑币机全屏广告图
        String[] merchantFullScreenBannerArray = new String[merchantFullScreenBannerVoList.size()];
        for (int i = 0; i < merchantFullScreenBannerVoList.size(); i++) {
            merchantFullScreenBannerArray[i] = merchantFullScreenBannerVoList.get(i).getFileName();
        }
        params.put("merchantFullScreenBannerArray", merchantFullScreenBannerArray);

        return ServerResponse.createBySuccess(params);
    }

    private JSONObject getDeviceInfoCommonV2(JSONObject params, DeviceVo deviceVo) throws Exception {
        // 获取设备秘钥
        DeviceVo device = deviceDao.findOneDevicePwd(deviceVo.getDeviceNo());
        if (StringUtils.isEmpty(device)) {
            throw new Exception("设备号不存在");
        }
        String productKeySign = KaiSaEncrypt.encryptKaiser(productKey);
        String secretSign = KaiSaEncrypt.encryptKaiser(device.getPassword());

        // 商家超级兑币机头部广告图
        List<MerchantBannerVo> merchantBannerVoList = new ArrayList<>();
        // 商家超级兑币机全屏广告图
        List<MerchantBannerVo> merchantFullScreenBannerVoList = new ArrayList<>();
        // 取客服电话
        String serviceMobilePhone = null;
        String serviceWeChatQr = null;
        if (!StringUtils.isEmpty(deviceVo.getMerchantStoreId()) && deviceVo.getMerchantStoreId().compareTo(0) == 1) {
            CustomerServiceInfo customerServiceInfo = customerServiceInfoService.findOneByMerchantStoreId(deviceVo.getMerchantStoreId());
            if (!StringUtils.isEmpty(customerServiceInfo)) {
                serviceMobilePhone = customerServiceInfo.getServiceMobilePhone();
                serviceWeChatQr = customerServiceInfo.getServiceWeChatQr();
            }

            MerchantBannerDto merchantBannerDto = new MerchantBannerDto();
            merchantBannerDto.setMerchantStoreId(deviceVo.getMerchantStoreId());
            merchantBannerDto.setStatus(1);
            merchantBannerDto.setDeviceId(deviceVo.getId());
            merchantBannerDto.setType(MerchantBannerTypeEnum.TOP_EXCLUSIVE.getCode());
            // 1、先查某场地某兑币机头部专属广告
            List<MerchantBannerVo> merchantBannerVos = merchantBannerService.findAllMerchantBannerByMerchantStoreId(merchantBannerDto);
            if (!StringUtils.isEmpty(merchantBannerVos) && merchantBannerVos.size() > 0) {
                merchantBannerVoList = merchantBannerVos;
            } else if (StringUtils.isEmpty(merchantBannerVos) || merchantBannerVos.size() == 0) {
                // 2、没有某场地某兑币机头部专属广告，就查该兑币机对应的场地头部广告
                merchantBannerDto.setDeviceId(null);
                merchantBannerDto.setType(MerchantBannerTypeEnum.TOP.getCode());
                merchantBannerVos = merchantBannerService.findAllMerchantBannerByMerchantStoreId(merchantBannerDto);

                if (StringUtils.isEmpty(merchantBannerVos) || merchantBannerVos.size() == 0) {
                    // 3、设备专属、场地都没有广告就默认系统的
                    merchantBannerDto.setMerchantStoreId(0);
                    merchantBannerVoList = merchantBannerService.findAllMerchantBannerByMerchantStoreId(merchantBannerDto);
                } else {
                    merchantBannerVoList = merchantBannerVos;
                }
            }

            merchantBannerDto.setMerchantStoreId(deviceVo.getMerchantStoreId());
            merchantBannerDto.setStatus(1);
            merchantBannerDto.setType(MerchantBannerTypeEnum.FULL_EXCLUSIVE.getCode());
            merchantBannerDto.setDeviceId(deviceVo.getId());
            // 查某台兑币机的全屏广告
            merchantFullScreenBannerVoList = merchantBannerService.findAllMerchantBannerByMerchantStoreId(merchantBannerDto);

            if (StringUtils.isEmpty(merchantFullScreenBannerVoList) || merchantFullScreenBannerVoList.size() == 0) {
                merchantBannerDto.setType(MerchantBannerTypeEnum.FULL_SCREEN.getCode());
                merchantBannerDto.setDeviceId(null);
                // 查某场地的兑币机全屏广告
                merchantFullScreenBannerVoList = merchantBannerService.findAllMerchantBannerByMerchantStoreId(merchantBannerDto);
            }
        }


        params.clear();
        params.put("deviceName", deviceVo.getDeviceNo());
        params.put("deviceTypeId", deviceVo.getDeviceTypeId());
        params.put("productKey", productKeySign);
        params.put("deviceSecret", secretSign);
        params.put("merchantStoreId", deviceVo.getMerchantStoreId());
        params.put("serviceMobilePhone", serviceMobilePhone);
        params.put("serviceWeChatQr", serviceWeChatQr);
        params.put("registerUrl", "http://weixin.qq.com/q/02pah3MCxfflD10000w03a");
        // 先默认平台企业微信客户群
        params.put("serviceEnterpriseWeChatGroupQr", "https://work.weixin.qq.com/m/66efa901b5fd01900ee8535dfe8542f6?is=174");
        String sign = MD5SignUtil.signTopRequestByMap(params, MD5SignUtil.secret);
        params.put("sign", sign);

        // 超级兑币机头部广告图
        String[] merchantBannerArray = new String[merchantBannerVoList.size()];
        for (int i = 0; i < merchantBannerVoList.size(); i++) {
            merchantBannerArray[i] = merchantBannerVoList.get(i).getFileName();
        }
        params.put("merchantBannerArray", merchantBannerArray);

        // 超级兑币机全屏广告图
        String[] merchantFullScreenBannerArray = new String[merchantFullScreenBannerVoList.size()];
        for (int i = 0; i < merchantFullScreenBannerVoList.size(); i++) {
            merchantFullScreenBannerArray[i] = merchantFullScreenBannerVoList.get(i).getFileName();
        }
        params.put("merchantFullScreenBannerArray", merchantFullScreenBannerArray);

        return params;
    }


    @Override
    public ServerResponse boxParameters(DeviceDto deviceDto) {
        if (StringUtils.isEmpty(deviceDto.getId())) {
            return ServerResponse.createByErrorMessage("参数错误");
        }
        DeviceVo oneDeviceByDeviceNo = deviceDao.findOneDeviceById(deviceDto.getUserInfo(), deviceDto.getId());
        if (ObjectUtils.isEmpty(oneDeviceByDeviceNo)) {
            return ServerResponse.createByErrorMessage("设备不存在");
        }
        if (oneDeviceByDeviceNo.getNetworkIntensity() < 1) {
            return ServerResponse.createByErrorMessage("设备不在线");
        }
        final String key = String.format(RedisKey.DEVICE_QUERY_PARAM, deviceDto.getDeviceNo());
        Integer existFlag = (Integer) redisCacheTemplate.opsForValue().get(key);
        if (!StringUtils.isEmpty(existFlag)) {
            return ServerResponse.createByErrorMessage("查询频繁，请稍后重试");
        }
        redisCacheTemplate.opsForValue().set(key, 1, 5, TimeUnit.SECONDS);
        try {
            final String tcp = PositiveDataFrameCMD.boxParamsQuery();
            pubService.pub(tcp, oneDeviceByDeviceNo.getDeviceNo(), productKey);
        } catch (Exception e) {
            e.printStackTrace();
            errorLogCommonService.writerInfoException(oneDeviceByDeviceNo.getDeviceNo() + "查询盒子的配置参数出错", oneDeviceByDeviceNo, e);
        }
        return ServerResponse.createBySuccess();
    }

    @Override
    public ServerResponse queryByCpuIdV2(DeviceDto deviceDto) throws Exception {
        if (StringUtils.isEmpty(deviceDto.getCpuId())) {
            return ServerResponse.createByErrorMessage("cpuId不能为空");
        }

        if (StringUtils.isEmpty(deviceDto.getAndroidMotherboardModel())) {
            return ServerResponse.createByErrorMessage("androidMotherboardModel不能为空");
        }

        if (StringUtils.isEmpty(deviceDto.getTimestamp())) {
            return ServerResponse.createByErrorMessage("timestamp不能为空");
        }

        if (StringUtils.isEmpty(deviceDto.getSign())) {
            return ServerResponse.createByErrorMessage("sign不能为空");
        }

        Map<String, Object> params = new HashMap<>();
        params.put("deviceNo", deviceDto.getDeviceNo());
        params.put("cpuId", deviceDto.getCpuId());
        params.put("androidMotherboardModel", deviceDto.getAndroidMotherboardModel());
        params.put("timestamp", deviceDto.getTimestamp());
        if (!StringUtils.isEmpty(deviceDto.getFirmwareVersion())) {
            params.put("firmwareVersion", deviceDto.getFirmwareVersion());
        }
        String checkSign = MD5SignUtil.signTopRequestByMap(params, MD5SignUtil.secret);
        if (!deviceDto.getSign().equalsIgnoreCase(checkSign)) {
            return ServerResponse.createByErrorMessage("校验不通过");
        }

        DeviceDto dto = new DeviceDto();
        dto.setCpuId(deviceDto.getCpuId());
        // 根据cpuId查询
        DeviceVo deviceVo = deviceDao.findOneDeviceByCondition(dto);
        if (StringUtils.isEmpty(deviceVo)) {
            // 根据设备号查询
            deviceVo = deviceDao.findOneDeviceByDeviceNo(deviceDto.getDeviceNo());
            if (StringUtils.isEmpty(deviceVo)) {
                return ServerResponse.createByErrorCodeMessage("10000", deviceDto.getCpuId() + "设备不存在");
            }

            if (StringUtils.isEmpty(deviceVo.getCpuId()) || !deviceDto.getCpuId().equalsIgnoreCase(deviceVo.getCpuId())) {
                // 更新设备的cpuID
                DeviceDto updateDeviceDto = new DeviceDto();
                updateDeviceDto.setId(deviceVo.getId());
                updateDeviceDto.setCpuId(deviceDto.getCpuId());
                deviceDao.updateDeviceById(updateDeviceDto);
            }
        }

        // 获取设备秘钥
        String productKeySign = KaiSaEncrypt.encryptKaiser(productKey);
        String secretSign = KaiSaEncrypt.encryptKaiser(deviceVo.getPassword());

        params.clear();
        params.put("productKey", productKeySign);
        params.put("deviceSecret", secretSign);

        // 商家超级兑币机头部广告图
        List<MerchantBannerVo> merchantBannerVoList = new ArrayList<>();
        // 商家超级兑币机全屏广告图
        List<MerchantBannerVo> merchantFullScreenBannerVoList = new ArrayList<>();
        // 取客服电话
        String serviceMobilePhone = null;
        String serviceWeChatQr = null;
        if (!StringUtils.isEmpty(deviceVo.getMerchantStoreId()) && deviceVo.getMerchantStoreId().compareTo(0) == 1) {
            CustomerServiceInfo customerServiceInfo = customerServiceInfoService.findOneByMerchantStoreId(deviceVo.getMerchantStoreId());
            if (!StringUtils.isEmpty(customerServiceInfo)) {
                serviceMobilePhone = customerServiceInfo.getServiceMobilePhone();
                serviceWeChatQr = customerServiceInfo.getServiceWeChatQr();
            }

            MerchantBannerDto merchantBannerDto = new MerchantBannerDto();
            merchantBannerDto.setMerchantStoreId(deviceVo.getMerchantStoreId());
            merchantBannerDto.setStatus(1);
            merchantBannerDto.setDeviceId(deviceVo.getId());
            merchantBannerDto.setType(MerchantBannerTypeEnum.TOP_EXCLUSIVE.getCode());
            // 1、先查某场地某兑币机头部专属广告
            List<MerchantBannerVo> merchantBannerVos = merchantBannerService.findAllMerchantBannerByMerchantStoreId(merchantBannerDto);
            if (!StringUtils.isEmpty(merchantBannerVos) && merchantBannerVos.size() > 0) {
                merchantBannerVoList = merchantBannerVos;
            } else if (StringUtils.isEmpty(merchantBannerVos) || merchantBannerVos.size() == 0) {
                // 2、没有某场地某兑币机头部专属广告，就查该兑币机对应的场地头部广告
                merchantBannerDto.setDeviceId(null);
                merchantBannerDto.setType(MerchantBannerTypeEnum.TOP.getCode());
                merchantBannerVos = merchantBannerService.findAllMerchantBannerByMerchantStoreId(merchantBannerDto);

                if (StringUtils.isEmpty(merchantBannerVos) || merchantBannerVos.size() == 0) {
                    // 3、设备专属、场地都没有广告就默认系统的
                    if (!StringUtils.isEmpty(deviceDto.getFirmwareVersion())) {
                        Integer firmwareVersion = (Integer) deviceDto.getFirmwareVersion();
                        if (firmwareVersion >= 135) {
                            //apk版本大于135，则先默认头部广告
                            merchantBannerVos = new LinkedList<>();
                            MerchantBannerVo item = new MerchantBannerVo();
                            item.setFileName("fixed/default_ad_1.png");
                            merchantBannerVos.add(item);
                        }
                    } else {
                        merchantBannerDto.setMerchantStoreId(0);
                        merchantBannerVoList = merchantBannerService.findAllMerchantBannerByMerchantStoreId(merchantBannerDto);
                    }
                } else {
                    merchantBannerVoList = merchantBannerVos;
                }
            }

            merchantBannerDto.setMerchantStoreId(deviceVo.getMerchantStoreId());
            merchantBannerDto.setStatus(1);
            merchantBannerDto.setType(MerchantBannerTypeEnum.FULL_EXCLUSIVE.getCode());
            merchantBannerDto.setDeviceId(deviceVo.getId());
            // 查某台兑币机的全屏广告
            merchantFullScreenBannerVoList = merchantBannerService.findAllMerchantBannerByMerchantStoreId(merchantBannerDto);

            if (StringUtils.isEmpty(merchantFullScreenBannerVoList) || merchantFullScreenBannerVoList.size() == 0) {
                merchantBannerDto.setType(MerchantBannerTypeEnum.FULL_SCREEN.getCode());
                merchantBannerDto.setDeviceId(null);
                // 查某场地的兑币机全屏广告
                merchantFullScreenBannerVoList = merchantBannerService.findAllMerchantBannerByMerchantStoreId(merchantBannerDto);
            }
        }


        params.put("deviceName", deviceVo.getDeviceNo());
        params.put("deviceTypeId", deviceVo.getDeviceTypeId());
        params.put("merchantStoreId", deviceVo.getMerchantStoreId());
        params.put("serviceMobilePhone", serviceMobilePhone);
        params.put("serviceWeChatQr", serviceWeChatQr);
        params.put("registerUrl", "http://weixin.qq.com/q/02pah3MCxfflD10000w03a");
        // 先默认平台企业微信客户群
        params.put("serviceEnterpriseWeChatGroupQr", "https://work.weixin.qq.com/m/66efa901b5fd01900ee8535dfe8542f6?is=174");
        String sign = MD5SignUtil.signTopRequestByMap(params, MD5SignUtil.secret);
        params.put("sign", sign);

        // 超级兑币机头部广告图
        String[] merchantBannerArray = new String[merchantBannerVoList.size()];
        for (int i = 0; i < merchantBannerVoList.size(); i++) {
            merchantBannerArray[i] = merchantBannerVoList.get(i).getFileName();
        }
        params.put("merchantBannerArray", merchantBannerArray);

        // 超级兑币机全屏广告图
        String[] merchantFullScreenBannerArray = new String[merchantFullScreenBannerVoList.size()];
        for (int i = 0; i < merchantFullScreenBannerVoList.size(); i++) {
            merchantFullScreenBannerArray[i] = merchantFullScreenBannerVoList.get(i).getFileName();
        }
        params.put("merchantFullScreenBannerArray", merchantFullScreenBannerArray);
        return ServerResponse.createBySuccess(params);
    }

    @Override
    public ServerResponse findAppLogDirList(AppFileDto appFileDto) {
        //兑币机
        List<AppFileDto> list = new ArrayList<>();
        if (appFileDto.getType() == 1) {
            redisCacheTemplate.delete(RedisKey.DEVICE_APP_FILE_LIST + appFileDto.getDeviceNo());
            //发送mqtt到设备上
            final String command = PositiveDataFrameCMD.penetrate(HuiLianDuiBiJiPositiveDataFrameCMD.notificationActiveReporting(appFileDto.getDirIndex()));
            pubService.pub(command, appFileDto.getDeviceNo(), productKey);
            //轮询查询数据
            final Boolean[] running = {true};
            Timer timer = new Timer();
            timer.schedule(new TimerTask() {
                @Override
                public void run() {
                    running[0] = false;
                }
            }, 8000);
            while (running[0]) {
                try {
                    //获取数据
                    List<AppFileDto> appFileDtoList = (List<AppFileDto>) redisCacheTemplate.opsForValue().get(RedisKey.DEVICE_APP_FILE_LIST + appFileDto.getDeviceNo());
                    if (!StringUtils.isEmpty(appFileDtoList) && appFileDtoList.size() > 0) {
                        list = appFileDtoList;
                        running[0] = false;
                        timer.cancel();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } else if (appFileDto.getType() == 2) {
            pubService.pub("uploadLog", appFileDto.getDeviceNo(), productKey);
        }
        return ServerResponse.createBySuccess(list);
    }

    @Override
    public ServerResponse noticeDownloadFile(AppFileDto appFileDto) {
        final String command = PositiveDataFrameCMD.penetrate(HuiLianDuiBiJiPositiveDataFrameCMD.notificationActiveReportingLogFile(appFileDto.getDirIndex(), appFileDto.getIndex()));

        pubService.pub(command, appFileDto.getDeviceNo(), productKey);
        return ServerResponse.createBySuccess();
    }

    @Override
    public ServerResponse uploadAppFile(MultipartFile file) throws IOException {
        if (file.isEmpty()) {
            return ServerResponse.createByError();
        }
        // 获取文件名
        String fileName = file.getOriginalFilename();
        // 获取文件的后缀名
        String suffixName = fileName.substring(fileName.lastIndexOf("."));
        if (".log".equals(suffixName) || ".txt".equals(suffixName)) {
            // 构建上传路径
            File dest = new File(fileProperties.getSaveImgPath() + fileName);
            // 检测是否存在目录
            if (!dest.getParentFile().exists()) {
                dest.getParentFile().mkdirs();
            }

            // 保存文件
            file.transferTo(dest);
            return ServerResponse.createBySuccess();
        }
        return ServerResponse.createByError();
    }

    @Override
    public ServerResponse remoteWriteDeviceNo(RemoteWriteDeivceNoDto remoteWriteDeivceNoDto) {
        redisCacheTemplate.delete(RedisKey.REMOTE_WRITE_DEVICENO + remoteWriteDeivceNoDto.getDeviceNo());
        DeviceVo oneDeviceByDeviceNo = deviceDao.findOneDeviceByDeviceNo(remoteWriteDeivceNoDto.getDeviceNo());

        if (oneDeviceByDeviceNo == null) {
            return ServerResponse.createByErrorMessage(remoteWriteDeivceNoDto.getDeviceNo() + "设备号不存在，请检查设备号！");
        }
        //判断设备号是否绑定
        if (oneDeviceByDeviceNo.getMerchantStoreId() != null && oneDeviceByDeviceNo.getMerchantStoreId() != -1) {
            return ServerResponse.createByErrorMessage(oneDeviceByDeviceNo.getDeviceNo() + "设备号已绑定场地，不允许烧录！");
        }
        Device device = deviceDao.findDeviceByUserIdAndDeviceNo(remoteWriteDeivceNoDto.getOriginalDeviceNo());
        if (device == null) {
            return ServerResponse.createByErrorMessage(remoteWriteDeivceNoDto.getOriginalDeviceNo() + "设备号不存在，请检查设备号！");
        }
        if (device.getMerchantStoreId() != null && device.getMerchantStoreId() != -1) {
            return ServerResponse.createByErrorMessage(device.getDeviceNo() + "设备号已绑定场地，不允许烧录！");
        }
        if (RoleEnum.AGENT.getRoleId().equals(remoteWriteDeivceNoDto.getUserInfo().getRoleId())) {
            if (!Objects.equals(device.getAgencyId(), remoteWriteDeivceNoDto.getUserInfo().getAgencyId())) {
                return ServerResponse.createByErrorMessage(device.getDeviceNo() + "未拥有该设备权限！");
            }
            if (!Objects.equals(oneDeviceByDeviceNo.getAgencyId(), remoteWriteDeivceNoDto.getUserInfo().getAgencyId())) {
                return ServerResponse.createByErrorMessage(oneDeviceByDeviceNo.getDeviceNo() + "未拥有该设备权限！");
            }
        }

        //发送mqtt到设备上
        final String command = RespondDataFrameCMD.remoteWriteDeviceNoCmd(remoteWriteDeivceNoDto.getDeviceNo(), productKey, oneDeviceByDeviceNo.getPassword());
        pubService.pub(command, remoteWriteDeivceNoDto.getOriginalDeviceNo(), productKey);
        //轮询查询数据
        final Boolean[] running = {true};
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                running[0] = false;
            }
        }, 4000);
        while (running[0]) {
            try {
                //获取数据
                String writeRet = (String) redisCacheTemplate.opsForValue().get(RedisKey.REMOTE_WRITE_DEVICENO + remoteWriteDeivceNoDto.getOriginalDeviceNo());
                if (!StringUtils.isEmpty(writeRet)) {
                    if (writeRet.equals("01")) {
                        return ServerResponse.createBySuccess();
                    } else {
                        return ServerResponse.createByErrorMessage("烧录失败，请重新烧录！");
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return ServerResponse.createByErrorMessage("发送烧录指令未返回，请后台确认是前后设备号EMQT连接情况");
    }

    /**
     * 设备批量上下架
     *
     * @param deviceDto
     * @return
     */
    @Override
    public ServerResponse batchUpdateStatus(DeviceDto deviceDto) {

        if (StringUtils.isEmpty(deviceDto.getUpdateStatus())) {
            return ServerResponse.createByErrorMessage("状态不能为空");
        }

        if (StringUtils.isEmpty(deviceDto.getDeviceIds()) || deviceDto.getDeviceIds().size() == 0) {
            return ServerResponse.createByErrorMessage("设备ID不能空");
        }
        List<DeviceVo> deviceVoList;
        //全选 通过传过来的条件查询
        if (!ObjectUtils.isEmpty(deviceDto.getDeviceAllSelected()) && deviceDto.getDeviceAllSelected()) {
            deviceVoList = deviceDao.findDeviceList(deviceDto);
        } else {
            deviceVoList = deviceDao.findAllDeviceByIdAndPermission(deviceDto);
        }

        if (StringUtils.isEmpty(deviceVoList) || deviceVoList.size() != deviceDto.getDeviceIds().size()) {
            return ServerResponse.createByErrorMessage("设备ID存在非法ID");
        }

        if (!DeviceStatusEnum.OFF_LINE.getCode().equals(deviceDto.getUpdateStatus()) && !DeviceStatusEnum.ON_LINE.getCode().equals(deviceDto.getUpdateStatus())) {
            return ServerResponse.createByErrorMessage("状态非法");
        }

        List<DeviceVo> deviceVos = new ArrayList<>();
        for (DeviceVo deviceVo : deviceVoList) {
            // 同为下架状态，不修改
            if (DeviceStatusEnum.OFF_LINE.getCode().equals(deviceDto.getUpdateStatus()) && DeviceStatusEnum.OFF_LINE.getCode().equals(deviceVo.getStatus())) {
                continue;
            }

            // 同为下架状态，不修改
            if (DeviceStatusEnum.ON_LINE.getCode().equals(deviceDto.getUpdateStatus()) && DeviceStatusEnum.ON_LINE.getCode().equals(deviceVo.getStatus())) {
                continue;
            }
            if (DeviceStatusEnum.OFF_LINE.getCode().equals(deviceVo.getStatus()) || DeviceStatusEnum.ON_LINE.getCode().equals(deviceVo.getStatus())) {
                // 必须为上架、下架状态才能修改
                DeviceVo vo = new DeviceVo();
                vo.setId(deviceVo.getId());
                vo.setStatus(deviceDto.getUpdateStatus());
                deviceVos.add(vo);
            }
        }

        if (deviceVos.size() > 0) {
            deviceDao.updateDeviceByIdToList(deviceVos);
        }


        return ServerResponse.createBySuccess();
    }

    /**
     * 获取设备二维码
     *
     * @param deviceDto
     * @return
     */
    @Override
    public ServerResponse getDeviceQrCode(DeviceDto deviceDto) {

        if (StringUtils.isEmpty(deviceDto.getDeviceIds()) || deviceDto.getDeviceIds().size() == 0) {
            return ServerResponse.createByErrorMessage("设备ID不能空");
        }

        List<DeviceVo> deviceVoList = deviceDao.findAllDeviceByIdAndPermission(deviceDto);
        if (deviceVoList.size() != deviceDto.getDeviceIds().size()) {
            return ServerResponse.createByErrorMessage("设备ID不存在或非法");
        }

        List<DeviceVo> deviceQrCodeList = new ArrayList<>();
        for (DeviceVo deviceVo : deviceVoList) {

            DeviceVo vo = new DeviceVo();
            vo.setId(deviceVo.getId());
            vo.setDeviceNo(deviceVo.getDeviceNo());

            MerchantStore merchantStore = null;
            if (!StringUtils.isEmpty(deviceVo.getMerchantStoreId()) && deviceVo.getMerchantStoreId() > 0) {
                MerchantStoreDto merchantStoreDto = new MerchantStoreDto();
                merchantStoreDto.setUserInfo(deviceDto.getUserInfo());
                merchantStoreDto.setId(deviceVo.getMerchantStoreId());
                merchantStore = merchantStoreService.findOneMerchantStoreByCondition(merchantStoreDto);
                vo.setStoreName(merchantStore.getStoreName());
            }

            final Agency agency = agencyService.findOneAgencyById(deviceVo.getAgencyId());
            StringBuffer qrLink = new StringBuffer();
            if (!StringUtils.isEmpty(merchantStore) && (!StringUtils.isEmpty(merchantStore.getDedicatedWeChatApplet()) || !StringUtils.isEmpty(merchantStore.getDedicatedALiApplet()) || !StringUtils.isEmpty(merchantStore.getDedicatedOfficialAccount()))) {
                // 商家-场地专属规则
                qrLink.append(configProperties.getClientBackEndUrl());
                if (deviceVo.getIsBluetooth()) {
                    // 蓝牙，专属微信小程序
                    log.info("蓝牙，商家专属微信小程序-处理");
                    qrLink.append("/client/applet/");
                    qrLink.append(merchantStore.getId());
                    qrLink.append("/deviceNo/");
                } else if (!StringUtils.isEmpty(merchantStore.getDedicatedWeChatApplet())) {
                    // 专属微信小程序
                    log.info("商家专属微信小程序-处理");
                    qrLink.append("/client/applet/");
                    qrLink.append(merchantStore.getId());
                    qrLink.append("/deviceNo/");
                } else if (!StringUtils.isEmpty(merchantStore.getDedicatedALiApplet())) {
                    // 专属支付宝小程序
                    log.info("商家专属支付宝小程序-处理");
                    qrLink.append("/client/applet/");
                    qrLink.append(merchantStore.getId());
                    qrLink.append("/deviceNo/");
                } else if (!StringUtils.isEmpty(merchantStore.getDedicatedOfficialAccount())) {
                    // 专属微信公众号
                    log.info("商家专属微信公众号-处理");
                    qrLink.append("/client/applet/");
                    qrLink.append(merchantStore.getId());
                    qrLink.append("/deviceNo/");
                } else {
                    throw new RuntimeException("商家专属规则配置异常");
                }
            } else if (!StringUtils.isEmpty(agency.getDedicatedWeChatApplet()) || !StringUtils.isEmpty(agency.getDedicatedALiApplet()) || !StringUtils.isEmpty(agency.getDedicatedOfficialAccount())) {
                // 合作伙伴专属规则
                AppletOrOfficialAccount appletOrOfficialAccount = null;
                // 蓝牙 > 专属微信公众号 > 专属微信小程序 = 专属支付宝小程序
                if (deviceVo.getIsBluetooth()) {
                    // 蓝牙
                    log.info("合作伙伴专属微信小程序-处理");
                    appletOrOfficialAccount = appletOrOfficialAccountCommonService.findOneById(agency.getDedicatedWeChatApplet());
                    if (StringUtils.isEmpty(appletOrOfficialAccount)) {
                        throw new RuntimeException("合作伙伴专属规则配置异常_4");
                    }
                    if (StringUtils.isEmpty(appletOrOfficialAccount.getDeviceQrCode())) {
                        throw new RuntimeException("合作伙伴专属规则配置异常_5");
                    }

                    qrLink = new StringBuffer(appletOrOfficialAccount.getUrl());
                    qrLink.append("/client/applet/device?d=");
                } else {
                    if (!StringUtils.isEmpty(agency.getDedicatedOfficialAccount())) {
                        // 专属微信公众号
                        log.info("合作伙伴专属微信公众号-处理");
                        appletOrOfficialAccount = appletOrOfficialAccountCommonService.findOneById(agency.getDedicatedOfficialAccount());
                    } else if (!StringUtils.isEmpty(agency.getDedicatedWeChatApplet())) {
                        // 专属微信小程序
                        log.info("合作伙伴专属微信小程序-处理");
                        appletOrOfficialAccount = appletOrOfficialAccountCommonService.findOneById(agency.getDedicatedWeChatApplet());
                    } else if (!StringUtils.isEmpty(agency.getDedicatedALiApplet())) {
                        // 专属支付宝小程序
                        log.info("合作伙伴专属支付宝小程序-处理");
                        appletOrOfficialAccount = appletOrOfficialAccountCommonService.findOneById(agency.getDedicatedALiApplet());
                    } else {
                        throw new RuntimeException("合作伙伴专属规则配置异常");
                    }

                    if (StringUtils.isEmpty(appletOrOfficialAccount)) {
                        throw new RuntimeException("合作伙伴专属规则配置异常_2");
                    }

                    if (StringUtils.isEmpty(appletOrOfficialAccount.getDeviceQrCode())) {
                        throw new RuntimeException("合作伙伴专属规则配置异常_3");
                    }

                    qrLink = new StringBuffer(appletOrOfficialAccount.getDeviceQrCode());
                }
            } else {
                // 没有专属，默认平台规则
                if (deviceVo.getIsBluetooth()) {
                    // 蓝牙
                    qrLink.append(configProperties.getClientBackEndUrl());
                    qrLink.append("/client/applet/device?d=");
                } else {
                    qrLink = new StringBuffer(configProperties.getDevicePayQrUrl());
                }
            }
            qrLink.append(deviceVo.getDeviceNo());

            if (DeviceTypeEnum.GASHAPON_MACHINE.getCode().equals(deviceVo.getDeviceTypeId())) {
                boolean contains = qrLink.toString().contains("?");
                if (!contains) {
                    qrLink.append("?");
                }

                if (!StringUtils.isEmpty(deviceDto.getHierarchy())) {
                    if (!qrLink.toString().endsWith("&")) {
                        qrLink.append("&");
                    }
                    qrLink.append("h=");
                    qrLink.append(deviceDto.getHierarchy());
                }

                if (!StringUtils.isEmpty(deviceDto.getFreightLane())) {
                    if (!qrLink.toString().endsWith("&")) {
                        qrLink.append("&");
                    }
                    qrLink.append("f=");
                    qrLink.append(deviceDto.getFreightLane());
                }
            }

            log.info("qrLink:{}", qrLink);
            vo.setFileName(qrLink.toString());
            deviceQrCodeList.add(vo);
        }

        log.info("deviceQrCodeList:{}", JSON.toJSONString(deviceQrCodeList));
        return ServerResponse.createBySuccess(deviceQrCodeList);
    }

    @Override
    public ServerResponse queryByCpuIdV3(DeviceDto deviceDto) throws IOException, NoSuchAlgorithmException {
        if (StringUtils.isEmpty(deviceDto.getCpuId())) {
            return ServerResponse.createByErrorMessage("cpuId不能为空");
        }

        if (StringUtils.isEmpty(deviceDto.getAndroidMotherboardModel())) {
            return ServerResponse.createByErrorMessage("androidMotherboardModel不能为空");
        }

        if (StringUtils.isEmpty(deviceDto.getTimestamp())) {
            return ServerResponse.createByErrorMessage("timestamp不能为空");
        }

        if (StringUtils.isEmpty(deviceDto.getSign())) {
            return ServerResponse.createByErrorMessage("sign不能为空");
        }

        Map<String, Object> params = new HashMap<>();
        params.put("deviceNo", deviceDto.getDeviceNo());
        params.put("cpuId", deviceDto.getCpuId());
        params.put("androidMotherboardModel", deviceDto.getAndroidMotherboardModel());
        params.put("timestamp", deviceDto.getTimestamp());
        if (!StringUtils.isEmpty(deviceDto.getFirmwareVersion())) {
            params.put("firmwareVersion", deviceDto.getFirmwareVersion());
        }
        String checkSign = MD5SignUtil.signTopRequestByMap(params, MD5SignUtil.secret);
        if (!deviceDto.getSign().equalsIgnoreCase(checkSign)) {
            return ServerResponse.createByErrorMessage("校验不通过");
        }

        DeviceDto dto = new DeviceDto();
        dto.setCpuId(deviceDto.getCpuId());
        // 根据cpuId查询
        DeviceVo deviceVo = deviceDao.findOneDeviceByCondition(dto);
        if (StringUtils.isEmpty(deviceVo)) {
            // 根据设备号查询
            deviceVo = deviceDao.findOneDeviceByDeviceNo(deviceDto.getDeviceNo());
            if (StringUtils.isEmpty(deviceVo)) {
                return ServerResponse.createByErrorCodeMessage("10000", deviceDto.getCpuId() + "设备不存在");
            }

            if (StringUtils.isEmpty(deviceVo.getCpuId()) || !deviceDto.getCpuId().equalsIgnoreCase(deviceVo.getCpuId())) {
                // 更新设备的cpuID
                DeviceDto updateDeviceDto = new DeviceDto();
                updateDeviceDto.setId(deviceVo.getId());
                updateDeviceDto.setCpuId(deviceDto.getCpuId());
                deviceDao.updateDeviceById(updateDeviceDto);
            }
        }

        // 获取设备秘钥
        String productKeySign = KaiSaEncrypt.encryptKaiser(productKey);
        String secretSign = KaiSaEncrypt.encryptKaiser(deviceVo.getPassword());

        params.clear();
        params.put("productKey", productKeySign);
        params.put("deviceSecret", secretSign);

        // 商家超级兑币机头部广告图
        List<MerchantBannerVo> merchantBannerVoList = new ArrayList<>();
        // 商家超级兑币机全屏广告图
        List<MerchantBannerVo> merchantFullScreenBannerVoList = new ArrayList<>();
        // 取客服电话
        String serviceMobilePhone = null;
        String serviceWeChatQr = null;
        if (!StringUtils.isEmpty(deviceVo.getMerchantStoreId()) && deviceVo.getMerchantStoreId().compareTo(0) == 1) {
            CustomerServiceInfo customerServiceInfo = customerServiceInfoService.findOneByMerchantStoreId(deviceVo.getMerchantStoreId());
            if (!StringUtils.isEmpty(customerServiceInfo)) {
                serviceMobilePhone = customerServiceInfo.getServiceMobilePhone();
                serviceWeChatQr = customerServiceInfo.getServiceWeChatQr();
            }

            MerchantBannerDto merchantBannerDto = new MerchantBannerDto();
            merchantBannerDto.setMerchantStoreId(deviceVo.getMerchantStoreId());
            merchantBannerDto.setStatus(1);
            merchantBannerDto.setDeviceId(deviceVo.getId());
            merchantBannerDto.setType(MerchantBannerTypeEnum.TOP_EXCLUSIVE.getCode());
            // 1、先查某场地某兑币机头部专属广告
            List<MerchantBannerVo> merchantBannerVos = merchantBannerService.findAllMerchantBannerByMerchantStoreId(merchantBannerDto);
            if (!StringUtils.isEmpty(merchantBannerVos) && merchantBannerVos.size() > 0) {
                merchantBannerVoList = merchantBannerVos;
            } else if (StringUtils.isEmpty(merchantBannerVos) || merchantBannerVos.size() == 0) {
                // 2、没有某场地某兑币机头部专属广告，就查该兑币机对应的场地头部广告
                merchantBannerDto.setDeviceId(null);
                merchantBannerDto.setType(MerchantBannerTypeEnum.TOP.getCode());
                merchantBannerVos = merchantBannerService.findAllMerchantBannerByMerchantStoreId(merchantBannerDto);

                if (StringUtils.isEmpty(merchantBannerVos) || merchantBannerVos.size() == 0) {
                    // 3、设备专属、场地都没有广告就默认系统的
                    if (!StringUtils.isEmpty(deviceDto.getFirmwareVersion())) {
                        Integer firmwareVersion = (Integer) deviceDto.getFirmwareVersion();
                        if (firmwareVersion >= 135) {
                            //apk版本大于135，则先默认头部广告
                            merchantBannerVos = new LinkedList<>();
                            MerchantBannerVo item = new MerchantBannerVo();
                            item.setFileName("fixed/default_ad_1.png");
                            merchantBannerVos.add(item);
                        }
                    } else {
                        merchantBannerDto.setMerchantStoreId(0);
                        merchantBannerVoList = merchantBannerService.findAllMerchantBannerByMerchantStoreId(merchantBannerDto);
                    }
                } else {
                    merchantBannerVoList = merchantBannerVos;
                }
            }

            merchantBannerDto.setMerchantStoreId(deviceVo.getMerchantStoreId());
            merchantBannerDto.setStatus(1);
            merchantBannerDto.setType(MerchantBannerTypeEnum.FULL_EXCLUSIVE.getCode());
            merchantBannerDto.setDeviceId(deviceVo.getId());
            // 查某台兑币机的全屏广告
            merchantFullScreenBannerVoList = merchantBannerService.findAllMerchantBannerByMerchantStoreId(merchantBannerDto);

            if (StringUtils.isEmpty(merchantFullScreenBannerVoList) || merchantFullScreenBannerVoList.size() == 0) {
                merchantBannerDto.setType(MerchantBannerTypeEnum.FULL_SCREEN.getCode());
                merchantBannerDto.setDeviceId(null);
                // 查某场地的兑币机全屏广告
                merchantFullScreenBannerVoList = merchantBannerService.findAllMerchantBannerByMerchantStoreId(merchantBannerDto);
            }
        }


        params.put("deviceName", deviceVo.getDeviceNo());
        params.put("deviceTypeId", deviceVo.getDeviceTypeId());
        params.put("merchantStoreId", deviceVo.getMerchantStoreId());

        if (StringUtils.isEmpty(deviceVo.getMerchantStoreId()) || deviceVo.getMerchantStoreId() <= 0) {
            params.put("dedicatedApplet", false);
        } else {
            MerchantStoreDto merchantStoreDto = new MerchantStoreDto();
            merchantStoreDto.setId(deviceVo.getMerchantStoreId());
            final MerchantStore merchantStore = merchantStoreService.findOneMerchantStoreByCondition(merchantStoreDto);
            if (
                    !StringUtils.isEmpty(merchantStore.getDedicatedWeChatApplet())
                            || !StringUtils.isEmpty(merchantStore.getDedicatedALiApplet())
                            || !StringUtils.isEmpty(merchantStore.getDedicatedOfficialAccount())) {
                // 专属小程序、公众号对应不同规则的二维码。APK端根据这个标识为true时将默认规则拼接成新规则
                params.put("dedicatedApplet", true);
            } else {
                params.put("dedicatedApplet", false);
            }
        }

        params.put("serviceMobilePhone", serviceMobilePhone);
        params.put("serviceWeChatQr", serviceWeChatQr);
        params.put("registerUrl", "http://weixin.qq.com/q/02pah3MCxfflD10000w03a");
        // 先默认平台企业微信客户群
        params.put("serviceEnterpriseWeChatGroupQr", "https://work.weixin.qq.com/m/66efa901b5fd01900ee8535dfe8542f6?is=174");

        // 超级兑币机头部广告图
        String[] merchantBannerArray = new String[merchantBannerVoList.size()];
        for (int i = 0; i < merchantBannerVoList.size(); i++) {
            merchantBannerArray[i] = merchantBannerVoList.get(i).getFileName();
        }
        params.put("merchantBannerArray", merchantBannerArray);

        // 超级兑币机全屏广告图
        String[] merchantFullScreenBannerArray = new String[merchantFullScreenBannerVoList.size()];
        for (int i = 0; i < merchantFullScreenBannerVoList.size(); i++) {
            merchantFullScreenBannerArray[i] = merchantFullScreenBannerVoList.get(i).getFileName();
        }
        params.put("merchantFullScreenBannerArray", merchantFullScreenBannerArray);

        String sign = MD5SignUtil.signTopRequestByMap(params, MD5SignUtil.secret);
        params.put("sign", sign);

        return ServerResponse.createBySuccess(params);
    }

    @Override
    public ServerResponse   vendingParameterSettings(DeviceDto deviceDto) {
        DeviceVo oneDeviceByDeviceNo = deviceDao.findOneDeviceByDeviceNo(deviceDto.getDeviceNo());
        if (oneDeviceByDeviceNo == null) {
            return ServerResponse.createByErrorMessage(deviceDto.getDeviceNo() + "设备号不存在，请检查设备号！");
        }
        if (RoleEnum.AGENT.getRoleId().equals(deviceDto.getUserInfo().getRoleId())) {
            if (!Objects.equals(oneDeviceByDeviceNo.getAgencyId(), deviceDto.getUserInfo().getAgencyId())) {
                return ServerResponse.createByErrorMessage(deviceDto.getDeviceNo() + "未拥有该设备权限！");
            }
        }
        String command = PositiveDataFrameCMD.penetrate(VendmachPositiveDataFrameCMD.updateConfiguration(deviceDto.getDeviceNo(), deviceDto));
        pubService.pub(command, deviceDto.getDeviceNo(), productKey);

        Device device = new Device();
        device.setId(oneDeviceByDeviceNo.getId());
        device.setDeviceTypeId(deviceDto.getDeviceTypeId());
        device.setLockTime(deviceDto.getLockTime());
        device.setHierarchySequence(deviceDto.getHierarchySequence());
        device.setFreightLaneSequence(deviceDto.getFreightLaneSequence());
        device.setFeedbackSequence(deviceDto.getFeedbackSequence());
        device.setReverseSequence(deviceDto.getReverseSequence());
        device.setDeliveryTime(deviceDto.getDeliveryTime());
        device.setPayLimitTime(deviceDto.getPayLimitTime());
//        device.setFeedback(deviceDto.getFeedback());
        deviceDao.updateVendingParameter(device);

        return ServerResponse.createBySuccess();

    }

    @Override
    public ServerResponse getConfiguration(DeviceDto deviceDto) {
        DeviceVo oneDeviceByDeviceNo = deviceDao.findOneDeviceByDeviceNo(deviceDto.getDeviceNo());
        if (oneDeviceByDeviceNo == null) {
            return ServerResponse.createByErrorMessage(deviceDto.getDeviceNo() + "设备号不存在，请检查设备号！");
        }
        if (RoleEnum.AGENT.getRoleId().equals(deviceDto.getUserInfo().getRoleId())) {
            if (!Objects.equals(oneDeviceByDeviceNo.getAgencyId(), deviceDto.getUserInfo().getAgencyId())) {
                return ServerResponse.createByErrorMessage(deviceDto.getDeviceNo() + "未拥有该设备权限！");
            }
        }
        String command = PositiveDataFrameCMD.penetrate(VendmachPositiveDataFrameCMD.getConfiguration(deviceDto.getDeviceNo()));
        pubService.pub(command, deviceDto.getDeviceNo(), productKey);
        return ServerResponse.createBySuccess();
    }

    /**
     * 烧录设备软件请求获取设备号、密码
     *
     * @param deviceDto
     * @return
     */
    @Override
    public ServerResponse getDeviceInfoFromBurningSoftware(DeviceDto deviceDto) throws IOException, NoSuchAlgorithmException {

        if (StringUtils.isEmpty(deviceDto.getDeviceNo())) {
            return ServerResponse.createByErrorMessage("设备号不能为空");
        }

        if (StringUtils.isEmpty(deviceDto.getSign())) {
            return ServerResponse.createByErrorMessage("加密串不能为空");
        }

        Map<String, Object> inParams = new HashMap<>();
        inParams.put("deviceNo", deviceDto.getDeviceNo());

        String checkSign = MD5SignUtil.signTopRequestByMap(inParams, MD5SignUtil.S_H_Secret);
        if (!deviceDto.getSign().equalsIgnoreCase(checkSign)) {
            return ServerResponse.createByErrorMessage("校验不通过");
        }

        DeviceVo oneDevicePwd = deviceDao.findOneDevicePwd(deviceDto.getDeviceNo());
        if (StringUtils.isEmpty(oneDevicePwd)) {
            return ServerResponse.createByErrorMessage("设备不存在");
        }

        String secretSign = KaiSaEncrypt.encryptKaiser(oneDevicePwd.getPassword());
        Map<String, Object> outParams = new HashMap<>();
        outParams.put("deviceNo", deviceDto.getDeviceNo());
        outParams.put("pwd", secretSign);

        return ServerResponse.createBySuccess(outParams);
    }

    /**
     * 获取售货机        <br/>
     * 返回参数             <br/>
     * deviceNo    设备号<br/>
     * productKey mqtt密钥<br/>
     * deviceSecret 设备密钥<br/>
     * serviceMobilePhone 客服电话<br/>
     * merchantStoreId 场地Id<br/>
     *
     * @param deviceDto
     * @return
     * @throws Exception
     */
    @Override
    public JSONObject findVendmachByCpuId(DeviceDto deviceDto) throws Exception {
        if (StringUtils.isEmpty(deviceDto.getCpuId())) {
            throw new Exception("cpuId不能为空");
        }

        if (StringUtils.isEmpty(deviceDto.getAndroidMotherboardModel())) {
            throw new Exception("androidMotherboardModel不能为空");
        }

        if (StringUtils.isEmpty(deviceDto.getTimestamp())) {
            throw new Exception("timestamp不能为空");
        }

        if (StringUtils.isEmpty(deviceDto.getSign())) {
            throw new Exception("sign不能为空");
        }

        JSONObject params = new JSONObject();
        params.put("deviceNo", deviceDto.getDeviceNo());
        params.put("cpuId", deviceDto.getCpuId());
        params.put("androidMotherboardModel", deviceDto.getAndroidMotherboardModel());
        params.put("timestamp", deviceDto.getTimestamp());
        String checkSign = MD5SignUtil.signTopRequestByJsonObject(params, MD5SignUtil.secret);
        if (!deviceDto.getSign().equalsIgnoreCase(checkSign)) {
            throw new Exception("校验不通过");
        }

        DeviceDto dto = new DeviceDto();
        dto.setCpuId(deviceDto.getCpuId());
        // 根据cpuId查询
        DeviceVo deviceVo = deviceDao.findOneDeviceByCondition(dto);
        if (StringUtils.isEmpty(deviceVo)) {
            // 根据设备号查询
            deviceVo = deviceDao.findOneDeviceByDeviceNo(deviceDto.getDeviceNo());
            if (StringUtils.isEmpty(deviceVo)) {
                return null;
            }

            if (StringUtils.isEmpty(deviceVo.getCpuId()) || !deviceDto.getCpuId().equalsIgnoreCase(deviceVo.getCpuId())) {
                // 更新设备的cpuID
                DeviceDto updateDeviceDto = new DeviceDto();
                updateDeviceDto.setId(deviceVo.getId());
                updateDeviceDto.setCpuId(deviceDto.getCpuId());
                deviceDao.updateDeviceById(updateDeviceDto);
            }
        }

        JSONObject returnParam = new JSONObject();
        returnParam.put("deviceNo", deviceVo.getDeviceNo());
        returnParam.put("productKey", KaiSaEncrypt.encryptKaiser(productKey));
        returnParam.put("deviceSecret", KaiSaEncrypt.encryptKaiser(deviceVo.getPassword()));

        //查找设置的客服电话
        if (!ObjectUtils.isEmpty(deviceVo.getMerchantStoreId())) {
            CustomerServiceInfo customerServiceInfo = customerServiceInfoService.getConsumerInfo(deviceVo.getMerchantStoreId());
            if (!ObjectUtils.isEmpty(customerServiceInfo.getServiceMobilePhone())) {
                returnParam.put("serviceMobilePhone", customerServiceInfo.getServiceMobilePhone());
            }
        }

        if (!ObjectUtils.isEmpty(deviceVo.getMerchantStoreId())) {
            returnParam.put("merchantStoreId", deviceVo.getMerchantStoreId());
        }

        return returnParam;
    }

    /**
     * 获取售货机        <br/>
     * 返回参数             <br/>
     * deviceNo    设备号<br/>
     * productKey mqtt密钥<br/>
     * deviceSecret 设备密钥<br/>
     *
     * @param deviceDto
     * @return
     * @throws Exception
     */
    @Override
    public JSONObject registerDeviceByAgencyNoV2(DeviceDto deviceDto) throws Exception {
        if (StringUtils.isEmpty(deviceDto.getAgencyNo())) {
            throw new Exception("agencyNo不能为空");
        }

        if (StringUtils.isEmpty(deviceDto.getCpuId())) {
            throw new Exception("cpuId不能为空");
        }

        if (StringUtils.isEmpty(deviceDto.getTimestamp())) {
            throw new Exception("timestamp不能为空");
        }

        if (StringUtils.isEmpty(deviceDto.getSign())) {
            throw new Exception("sign不能为空");
        }

        JSONObject params = new JSONObject();
        params.put("agencyNo", deviceDto.getAgencyNo());
        params.put("cpuId", deviceDto.getCpuId());
        params.put("timestamp", deviceDto.getTimestamp());
        params.put("deviceRegisterType", deviceDto.getDeviceRegisterType());

        String checkSign = MD5SignUtil.signTopRequestByJsonObject(params, MD5SignUtil.secret);
        if (!deviceDto.getSign().equalsIgnoreCase(checkSign)) {
            throw new Exception("校验不通过");
        }

        log.warn("deviceDto：{}", JSON.toJSONString(deviceDto));

        deviceDto.setStatus(DeviceStatusEnum.NON_ACTIVATED.getCode());
        if (DeviceRegisterTypeEnum.SUPER_MONEY_CHANGER.getCode().equals(deviceDto.getDeviceRegisterType())) {
            // 超级兑币机分配设备号
            deviceDto.setIsAndroid(true);
        } else if (DeviceRegisterTypeEnum.DEPOSIT_COINS_AND_BILLS.getCode().equals(deviceDto.getDeviceRegisterType())) {
            // 存币存票分配设备号
            deviceDto.setIsDepositCoinsAndBills(true);
        } else if (DeviceRegisterTypeEnum.GATE.getCode().equals(deviceDto.getDeviceRegisterType())) {
            // 门闸分配设备号
            deviceDto.setIsGate(true);
        } else if (DeviceRegisterTypeEnum.VENDMACH.getCode().equals(deviceDto.getDeviceRegisterType())) {
            // 门闸分配设备号
            deviceDto.setIsVendmach(true);
        } else {
            throw new RuntimeException("deviceRegisterType有误");
        }
        DeviceVo deviceVo = deviceDao.findOneDeviceByNotAllocated(deviceDto);

        if (StringUtils.isEmpty(deviceVo)) {
            throw new RuntimeException("合作伙伴暂无可分配的设备号");
        }

        // 设置为已分配
        DeviceDto updateDeviceDto = new DeviceDto();
        updateDeviceDto.setId(deviceVo.getId());
        updateDeviceDto.setCpuId(deviceDto.getCpuId());
        updateDeviceDto.setIsAllocated(true);
        updateDeviceDto.setStatus(DeviceStatusEnum.ON_LINE.getCode());
        deviceDao.updateDeviceById(updateDeviceDto);

        JSONObject returnParam = new JSONObject();
        returnParam.put("deviceNo", deviceVo.getDeviceNo());
        returnParam.put("productKey", KaiSaEncrypt.encryptKaiser(productKey));
        returnParam.put("deviceSecret", KaiSaEncrypt.encryptKaiser(deviceVo.getPassword()));
        returnParam.put("registerUrl", "http://weixin.qq.com/q/02pah3MCxfflD10000w03a");

        return returnParam;
    }

    @Override
    public Exception statsDayDeviceJob() {
        Exception temp = null;
        Integer[] deviceTypeIdArray = new Integer[]{
                DeviceTypeEnum.BLEND_VENDING_MACHINE.getCode(),
                DeviceTypeEnum.VENDING_MACHINE.getCode(),
                DeviceTypeEnum.SCREEN_VENDING_MACHINE.getCode(),
                DeviceTypeEnum.OPEN_DOOR_VENDING_MACHINE.getCode()
        };
        Integer[] agencyIdArray = new Integer[]{111, 120, 154, 126, 140};
        try {
            List<DeviceVo> deviceVoList = deviceDao.findDeviceByAgencyId(deviceTypeIdArray, agencyIdArray);
            if (StringUtils.isEmpty(deviceVoList) || deviceVoList.size() == 0) {
                return temp;
            }

            for (DeviceVo deviceVo : deviceVoList) {
                final DeviceAnnualFeeVo deviceAnnualFeeVo = deviceAnnualFeeService.getOneDeviceAnnualFeeByDeviceId(deviceVo.getId(), deviceVo.getUserId(), deviceVo.getMerchantStoreId());
                if (!StringUtils.isEmpty(deviceAnnualFeeVo)) {
                    continue;
                }

                //添加数据
                final OrderVo orderVo = orderService.getOneOrderByDeviceNo(deviceVo.getDeviceNo(), deviceVo.getUserId(), deviceVo.getMerchantStoreId());
                if (StringUtils.isEmpty(orderVo)) {
                    continue;
                }

                DeviceAnnualFeeDto dto = new DeviceAnnualFeeDto();
                dto.setUserId(deviceVo.getUserId());
                dto.setMerchantStoreId(deviceVo.getMerchantStoreId());
                dto.setDefaultMode(1);
                dto.setUnitPrice(BigDecimal.valueOf(20));
                dto.setDeviceId(deviceVo.getId());
                dto.setDateOfFirstUse(orderVo.getGmtPayment());
                // 加上一年 使用 Calendar 类来操作日期
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(orderVo.getGmtPayment());
                calendar.add(Calendar.YEAR, 1); // 增加一年
                // 得到增加一年后的日期
                Date newDate = calendar.getTime();
                dto.setDueDate(newDate);
                deviceAnnualFeeService.addDeviceAnnualFee(dto);
            }
        } catch (Exception e) {
            e.printStackTrace();
            temp = e;
        }
        return temp;
    }


    private JSONArray getList(List<ProductParamDataVo> list) {
        JSONArray basicParamDataJson = new JSONArray();
        for (int i = 0; i < list.size(); i++) {
            final ProductParamDataVo item = list.get(i);
            String jsonString = JSON.toJSONString(item);
            JSONObject jsonItem = JSON.parseObject(jsonString);
            basicParamDataJson.add(jsonItem);
        }
        return basicParamDataJson;
    }


    private void compoundJson(JSONArray jsonArray, List<ProductFuncVo> list) {
        for (int i = 0; i < list.size(); i++) {
            JSONObject jsonObject = new JSONObject();
            final ProductFuncVo productFuncVo = list.get(i);
            jsonObject.put("deviceTypeId", productFuncVo.getDeviceTypeId());
            jsonObject.put("productFuncId", productFuncVo.getId());
            jsonObject.put("funcName", productFuncVo.getFuncName());
            jsonObject.put("funcType", productFuncVo.getFuncType());
            jsonObject.put("queryFunCode", productFuncVo.getQueryFunCode());
            jsonObject.put("setFunCode", productFuncVo.getSetFunCode());
            jsonObject.put("visible", productFuncVo.getVisible());
            jsonObject.put("disable", productFuncVo.getDisable());
            List<ProductParamDataVo> basicParamDataList = productFuncVo.getBasicParamDataList();
            jsonObject.put("basicParamDataList", this.getList(basicParamDataList));
            jsonArray.add(jsonObject);
        }
    }

}
